【发布时间】:2009-05-06 06:54:12
【问题描述】:
我正在为 C#.NET 3.5 中的自定义 ConfigurationHandler 编写自定义 ConfigurationElementCollection,我希望将 IEnumerator 公开为通用 IEnumerator。
实现这一目标的最佳方法是什么?
我目前正在使用代码:
公共新 IEnumerator干杯
【问题讨论】:
标签: c# enumeration ienumerator
我正在为 C#.NET 3.5 中的自定义 ConfigurationHandler 编写自定义 ConfigurationElementCollection,我希望将 IEnumerator 公开为通用 IEnumerator。
实现这一目标的最佳方法是什么?
我目前正在使用代码:
公共新 IEnumerator干杯
【问题讨论】:
标签: c# enumeration ienumerator
我不相信框架中有任何内容,但您可以轻松编写一个:
IEnumerator<T> Cast<T>(IEnumerator iterator)
{
while (iterator.MoveNext())
{
yield return (T) iterator.Current;
}
}
从 LINQ 调用 Enumerable.Cast<T> 然后在结果上调用 GetEnumerator() 是很诱人的——但是如果你的类已经实现了 IEnumerable<T> 并且 T 是一个值类型,那么它就相当于一个空操作,所以GetEnumerator() 调用递归并抛出 StackOverflowException。当foo 绝对是一个不同的 对象(它不会委托回这个对象)时,使用return foo.Cast<T>.GetEnumerator(); 是安全的,否则,您最好使用上面的代码。
【讨论】:
this.Cast<T>().GetEnumerator() 解决方案,在相同的场景中(虽然我是从IEnumerable<T> 派生的),但我遇到了堆栈溢出。
IEnumerable<T> 已经派生自IEnumerable,因此无需进行任何转换。您可以简单地对其进行强制转换...实际上它是隐含的,不需要强制转换。
IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();
使用 LINQ 反之亦然:
var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
【讨论】:
您可以使用OfType<T> 和Cast<T>。
public static IEnumerable Digits()
{
return new[]{1, 15, 68, 1235, 12390, 1239};
}
var enumerable = Digits().OfType<int>();
foreach (var item in enumerable)
// var is here an int. Without the OfType<int(), it would be an object
Console.WriteLine(i);
要获得IEnumerator<T> 而不是IEnumerable<T>,您只需致电GetEnumerator()
var enumerator = Digits().OfType<int>().GetEnumerator();
【讨论】:
我遇到了同样的堆栈溢出问题,其中提到了一些 cmets。在我的情况下,这是因为 GetEnumerator 调用需要对 base.GetEnumerator 进行,否则您将在自己的 GetEnumerator 重新定义中循环。
这是引发堆栈溢出的代码。 foreach 语句的使用调用了我试图重载的同一个 GetEnumerator 函数:
public new IEnumerator<T> GetEnumerator()
{
foreach (T type in this)
{
yield return type;
}
}
我最终得到了原始帖子的简化版本,因为您不需要使用列表持有人。
public class ElementCollection<T> : ConfigurationElementCollection, IList<T>
...
public new IEnumerator<T> GetEnumerator()
{
var baseEnum = base.GetEnumerator();
while (baseEnum.MoveNext())
{
yield return baseEnum.Current as T;
}
}
...
}
【讨论】:
这对我有用。
IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
【讨论】: