Mar*_*zek 6 c# ienumerator list
尽管事实上,IEnumerator.Reset永远不应该使用该方法,但我发现了方法实现的奇怪行为List<T>.
无论您如何检查.NET Framework源代码(尝试使用参考源和ILSpy),该方法都实现如下:
void System.Collections.IEnumerator.Reset() {
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = 0;
current = default(T);
}
Run Code Online (Sandbox Code Playgroud)
但是,看起来这个方法根本就没有被调用过!考虑一下代码:
var list = new List<int>(1) { 3 };
using (var e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
((IEnumerator)e).Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
Run Code Online (Sandbox Code Playgroud)
这是很清楚的,它应打印True和3的两倍.而不是结果
True
3
False
0
Run Code Online (Sandbox Code Playgroud)
我错过了任何简单的解释?
Jon*_*eet 15
我错过了任何简单的解释?
是的:你在List.Enumerator这里拳击:
((IEnumerator)e).Reset();
Run Code Online (Sandbox Code Playgroud)
这需要现有的副本并重置它 - 将原件保留为一件.
要重置实际的枚举器,你需要这样的东西:
var list = new List<int>(1) { 3 };
var e = list.GetEnumerator();
// Can't use "ref" with a using statement
try
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
Reset(ref e);
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
finally
{
e.Dispose();
}
static void Reset<T>(ref T enumerator) where T : IEnumerator
{
enumerator.Reset();
}
Run Code Online (Sandbox Code Playgroud)
这很棘手,因为它使用显式接口实现.
我没有测试过,但我认为这对你有用.显然,这是一个坏主意,做这个...
编辑:或者,只需将您的变量类型更改为IEnumerator或IEnumerator<int>开始.然后它将被装箱一次,该Reset方法将改变盒装值:
var list = new List<int>(1) { 3 };
using (IEnumerator e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
e.Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1842 次 |
| 最近记录: |