从数组中获取generics枚举器

在C#中,如何获得给定数组的generics枚举?

在下面的代码中, MyArray是一个MyType对象的数组。 我想以所示的方式获得MyIEnumerator ,但似乎我得到一个空的枚举(虽然我已经证实MyArray.Length > 0 )。

 MyType [ ] MyArray = ... ; IEnumerator<MyType> MyIEnumerator = ( MyArray.GetEnumerator() as IEnumerator<MyType> ) ; 

适用于2.0+:

 ((IEnumerable<MyType>)myArray).GetEnumerator() 

适用于3.5+(花式LINQy,效率稍低):

 myArray.Cast<MyType>().GetEnumerator() // returns IEnumerator<MyType> 

你可以自己决定是否铸造丑陋足以保证一个无关的图书馆电话:

 int[] arr; IEnumerator<int> Get1() { return ((IEnumerable<int>)arr).GetEnumerator(); // <-- 1 non-local call // L_0001: ldarg.0 // L_0002: ldfld int32[] agree.foo::arr // L_0007: castclass [mscorlib]System.Collections.Generic.IEnumerable`1<int32> // L_000c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator() // L_0011: stloc.0 } IEnumerator<int> Get2() { return arr.AsEnumerable().GetEnumerator(); // <-- 2 non-local calls // L_0001: ldarg.0 // L_0002: ldfld int32[] agree.foo::arr // L_0007: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::AsEnumerable<int32>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>) // L_000c: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator() // L_0011: stloc.0 } 

为了完整起见,还应该注意以下内容是不正确的 – 并且会在运行时崩溃,因为T[]select通用IEnumerable接口作为GetEnumerator()默认(即非显式)实现。

 IEnumerator<int> NoGet() // error - do not use { return (IEnumerator<int>)arr.GetEnumerator(); // L_0001: ldarg.0 // L_0002: ldfld int32[] agree.foo::arr // L_0007: callvirt instance class [mscorlib]System.Collections.IEnumerator [mscorlib]System.Array::GetEnumerator() // L_000c: castclass [mscorlib]System.Collections.Generic.IEnumerator`1<int32> // L_0011: stloc.0 } 

神秘的是,为什么SZGenericArrayEnumerator<T>不是从SZArrayEnumeratorinheritance的SZArrayEnumerator一个内部类,它当前被标记为'sealed' – 因为这将允许(协变)generics枚举器被默认返回?

由于我不喜欢演员,所以稍作更新:

 your_array.AsEnumerable().GetEnumerator(); 

为了让它尽可能的干净,我喜欢让编译器完成所有的工作。 没有演员(所以它实际上是types安全的)。 没有使用第三方库(System.Linq)(没有运行时间开销)。

  public static IEnumerable<T> GetEnumerable<T>(this T[] arr) { return arr; } 

//并使用代码:

  String[] arr = new String[0]; arr.GetEnumerable().GetEnumerator() 

这利用了一些编译器的魔力,保持一切干净。

另一点需要注意的是我的答案是编译时检查的唯一答案。

对于任何其他解决scheme,如果“arr”types发生变化,则调用代码将被编译,并在运行时失败,从而导致运行时错误。

我的答案将导致代码不能编译,因此我有更less的机会在我的代码中发送错误,因为它会告诉我,我使用了错误的types。

。YourArray.OfType()的GetEnumerator();

可能会更好一些,因为它只需要检查types,而不是投射。

  MyType[] arr = { new MyType(), new MyType(), new MyType() }; IEnumerable<MyType> enumerable = arr; IEnumerator<MyType> en = enumerable.GetEnumerator(); foreach (MyType item in enumerable) { } 

当然,你可以做的只是实现你自己的generics枚举数组。

 using System.Collections; using System.Collections.Generic; namespace SomeNamespace { public class ArrayEnumerator<T> : IEnumerator<T> { public ArrayEnumerator(T[] arr) { collection = arr; length = arr.Length; } private readonly T[] collection; private int index = -1; private readonly int length; public T Current { get { return collection[index]; } } object IEnumerator.Current { get { return Current; } } public bool MoveNext() { index++; return index < length; } public void Reset() { index = -1; } public void Dispose() {/* Nothing to dispose. */} } } 

这或多或less等于Glenn Slayden提到的SZGenericArrayEnumerator <T>的.NET实现。 你当然只能这样做,这是值得的。 在大多数情况下不是。