Jay*_*Fix 83 c# arrays generics ienumerator
在C#中,如何从给定数组中获取通用枚举器?
在下面的代码中,MyArray是一个MyType对象数组.我想以MyIEnumerator所示的方式获得,但似乎我获得了一个空的调查员(尽管我已经证实了这一点MyArray.Length > 0).
MyType [ ] MyArray = ... ;
IEnumerator<MyType> MyIEnumerator
= ( MyArray.GetEnumerator() as IEnumerator<MyType> ) ;
Run Code Online (Sandbox Code Playgroud)
Meh*_*ari 90
适用于2.0+:
((IEnumerable<MyType>)myArray).GetEnumerator()
Run Code Online (Sandbox Code Playgroud)
适用于3.5+(花哨的LINQy,效率稍差):
myArray.Cast<MyType>().GetEnumerator() // returns IEnumerator<MyType>
Run Code Online (Sandbox Code Playgroud)
Gle*_*den 48
你可以自己决定是否有足够的魔法来保证一个无关的库调用:
int[] arr;
IEnumerator<int> Get1()
{
return ((IEnumerable<int>)arr).GetEnumerator(); // <-- 1 non-local call
// ldarg.0
// ldfld int32[] foo::arr
// castclass System.Collections.Generic.IEnumerable`1<int32>
// callvirt instance class System.Collections.Generic.IEnumerator`1<!0> System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
}
IEnumerator<int> Get2()
{
return arr.AsEnumerable().GetEnumerator(); // <-- 2 non-local calls
// ldarg.0
// ldfld int32[] foo::arr
// call class System.Collections.Generic.IEnumerable`1<!!0> System.Linq.Enumerable::AsEnumerable<int32>(class System.Collections.Generic.IEnumerable`1<!!0>)
// callvirt instance class System.Collections.Generic.IEnumerator`1<!0> System.Collections.Generic.IEnumerable`1<int32>::GetEnumerator()
}
Run Code Online (Sandbox Code Playgroud)
并且为了完整性,还应该注意以下内容不正确 - 并且将在运行时崩溃 - 因为T[]选择非通用IEnumerable接口用于其默认(即非显式)实现GetEnumerator().
IEnumerator<int> NoGet() // error - do not use
{
return (IEnumerator<int>)arr.GetEnumerator();
// ldarg.0
// ldfld int32[] foo::arr
// callvirt instance class System.Collections.IEnumerator System.Array::GetEnumerator()
// castclass System.Collections.Generic.IEnumerator`1<int32>
}
Run Code Online (Sandbox Code Playgroud)
问题是,为什么不SZGenericArrayEnumerator<T>继承SZArrayEnumerator- 当前标记为"密封"的内部类 - 因为这将允许(协变)通用枚举器默认返回?
gre*_*man 23
由于我不喜欢施法,所以稍微更新一下:
your_array.AsEnumerable().GetEnumerator();
Run Code Online (Sandbox Code Playgroud)
为了使它尽可能干净,我喜欢让编译器完成所有工作.没有演员表(所以它实际上是类型安全的).没有使用第三方库(System.Linq)(没有运行时开销).
public static IEnumerable<T> GetEnumerable<T>(this T[] arr)
{
return arr;
}
Run Code Online (Sandbox Code Playgroud)
//并使用代码:
String[] arr = new String[0];
arr.GetEnumerable().GetEnumerator()
Run Code Online (Sandbox Code Playgroud)
这利用了一些编译器魔法,可以保持一切清洁.
另一点需要注意的是,我的答案是进行编译时检查的唯一答案.
对于任何其他解决方案,如果"arr"的类型发生更改,则调用代码将进行编译,并在运行时失败,从而导致运行时错误.
我的答案将导致代码无法编译,因此我在代码中发送错误的机会较少,因为它会向我发出信号,表明我使用了错误的类型.
| 归档时间: |
|
| 查看次数: |
19131 次 |
| 最近记录: |