C# 将 IEnumerator 转换为通用 IEnumerator 的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/828342/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to convert an IEnumerator to a generic IEnumerator?
提问by zonkflut
I am writing a custom ConfigurationElementCollection for a custom ConfigurationHandler in C#.NET 3.5 and I am wanting to expose the IEnumerator as a generic IEnumerator.
我正在为 C#.NET 3.5 中的自定义 ConfigurationHandler 编写自定义 ConfigurationElementCollection,我想将 IEnumerator 公开为通用 IEnumerator。
What would be the best way to achieve this?
实现这一目标的最佳方法是什么?
I am currently using the code:
我目前正在使用代码:
public new IEnumerator<GenericObject> 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(); }
Cheers
干杯
采纳答案by Jon Skeet
I don't believe there's anything in the framework, but you could easily write one:
我不相信框架中有任何内容,但您可以轻松编写一个:
IEnumerator<T> Cast<T>(IEnumerator iterator)
{
while (iterator.MoveNext())
{
yield return (T) iterator.Current;
}
}
It's tempting to just call Enumerable.Cast<T>
from LINQ and then call GetEnumerator()
on the result - but if your class already implements IEnumerable<T>
and T
is a value type, that acts as a no-op, so the GetEnumerator()
call recurses and throws a StackOverflowException
. It's safe to use return foo.Cast<T>.GetEnumerator();
when foo
is definitely a differentobject (which doesn't delegate back to this one) but otherwise, you're probably best off using the code above.
很容易只Enumerable.Cast<T>
从 LINQ调用然后调用GetEnumerator()
结果 - 但如果你的类已经实现IEnumerable<T>
并且T
是一个值类型,那么它作为一个空操作,所以GetEnumerator()
调用会递归并抛出一个StackOverflowException
. 使用return foo.Cast<T>.GetEnumerator();
whenfoo
绝对是一个不同的对象(它不会委托回这个对象)是安全的,但除此之外,您最好使用上面的代码。
回答by Paul Alexander
IEnumerable<T>
already derives from IEnumerable
so there's no need to do any conversion. You can simply cast to it...well actually it's implicit no cast necessary.
IEnumerable<T>
已经派生自,IEnumerable
因此无需进行任何转换。你可以简单地投射到它......实际上它是隐含的,不需要强制转换。
IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();
Going the other way round isn't much more difficult with LINQ:
反过来,使用 LINQ 并不困难:
var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();
回答by Svish
You can use OfType<T>
and Cast<T>
.
您可以使用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);
To get an IEnumerator<T>
instead of an IEnumerable<T>
you can just make a call to GetEnumerator()
要得到一个IEnumerator<T>
而不是一个,IEnumerable<T>
你可以打电话给GetEnumerator()
var enumerator = Digits().OfType<int>().GetEnumerator();
回答by DenverYogi
This works for me.
这对我有用。
IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
回答by VeV
I was running into the same Stack Overflow problem mentioned is some of the comments. In my case it was due to the fact that the GetEnumerator call needed to be to the base.GetEnumerator otherwise you loop within your own GetEnumerator redefinition.
我遇到了相同的堆栈溢出问题,其中提到了一些评论。就我而言,这是因为 GetEnumerator 调用需要对 base.GetEnumerator 进行调用,否则您将在自己的 GetEnumerator 重新定义中循环。
This is the code that was Throwing the Stack Overflow. The use of the foreach statement call the same GetEnumerator function I'm trying to overload:
这是引发堆栈溢出的代码。foreach 语句的使用调用了我试图重载的同一个 GetEnumerator 函数:
public new IEnumerator<T> GetEnumerator()
{
foreach (T type in this)
{
yield return type;
}
}
I've ended up with a simplified version of the original post as you don't need to use a List holder.
我最终得到了原始帖子的简化版本,因为您不需要使用列表持有者。
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;
}
}
...
}