将IEnumerator转换为通用IEnumerator的最佳方法是什么?
我正在为C#.NET 3.5中的自定义ConfigurationHandler编写自定义ConfigurationElementCollection,并且我希望将IEnumerator公开为通用IEnumerator。
实现这一目标的最佳方法是什么?
我目前正在使用代码:
public new IEnumerator GetEnumerator(){var list = new List(); var baseEnum = base.GetEnumerator(); while(baseEnum.MoveNext()){var obj = baseEnum.Current as GenericObject; if(obj!= null)list.Add(obj); } return list.GetEnumerator(); }
干杯
我不相信框架中有任何内容,但您可以轻松地编写一个:
IEnumerator Cast (IEnumerator iterator) { while (iterator.MoveNext()) { yield return (T) iterator.Current; } }
从LINQ调用Enumerable.Cast
然后在结果上调用GetEnumerator()
很诱人 – 但是如果你的类已经实现了IEnumerable
而T
是一个值类型,那么它就像一个no-op,所以GetEnumerator()
调用recurses并抛出StackOverflowException
。 使用return foo.Cast
当foo
绝对是一个不同的对象(它不会委托给这个对象),但除此之外,你可能最好使用上面的代码。
IEnumerable
已经从IEnumerable
派生,所以不需要进行任何转换。 你可以简单地投射到它……实际上它是隐含的,没有必要。
IEnumerable enumerable = GetGenericFromSomewhere(); IEnumerable sadOldEnumerable = enumerable; return sadOldEnumerable.GetEnumerator();
对于LINQ来说,反过来说并不困难:
var fancyEnumerable = list.OfType(); return fancyEnumerable.GetEnumerator();
您可以使用OfType
和Cast
。
public static IEnumerable Digits() { return new[]{1, 15, 68, 1235, 12390, 1239}; } var enumerable = Digits().OfType(); foreach (var item in enumerable) // var is here an int. Without the OfType
要获取IEnumerator
而不是IEnumerable
您只需调用GetEnumerator()
var enumerator = Digits().OfType().GetEnumerator();
这对我有用。
IEnumerator columnEnumerator = dt.Columns.Cast ().GetEnumerator();
我遇到了同样的Stack Overflow问题,提到了一些评论。 在我的情况下,这是因为GetEnumerator调用需要是base.GetEnumerator,否则你在自己的GetEnumerator重定义中循环。
这是抛出堆栈溢出的代码。 使用foreach语句调用我正在尝试重载的相同GetEnumerator函数:
public new IEnumerator GetEnumerator() { foreach (T type in this) { yield return type; } }
我最终得到了原始post的简化版本,因为您不需要使用列表持有者。
public class ElementCollection : ConfigurationElementCollection, IList ... public new IEnumerator GetEnumerator() { var baseEnum = base.GetEnumerator(); while (baseEnum.MoveNext()) { yield return baseEnum.Current as T; } } ... }