【发布时间】:2015-05-27 15:30:00
【问题描述】:
我想通过List<int> 枚举并调用异步方法。
如果我这样做:
public async Task NotWorking() {
var list = new List<int> {1, 2, 3};
using (var enumerator = list.GetEnumerator()) {
Trace.WriteLine(enumerator.MoveNext());
Trace.WriteLine(enumerator.Current);
await Task.Delay(100);
}
}
结果是:
True
0
但我希望它是:
True
1
如果我删除 using 或 await Task.Delay(100):
public void Working1() {
var list = new List<int> {1, 2, 3};
using (var enumerator = list.GetEnumerator()) {
Trace.WriteLine(enumerator.MoveNext());
Trace.WriteLine(enumerator.Current);
}
}
public async Task Working2() {
var list = new List<int> {1, 2, 3};
var enumerator = list.GetEnumerator();
Trace.WriteLine(enumerator.MoveNext());
Trace.WriteLine(enumerator.Current);
await Task.Delay(100);
}
输出如预期:
True
1
谁能向我解释这种行为?
【问题讨论】:
-
@MarcGravell 是,刚刚检查了生成的IL。
-
一个懒惰的“修复”是使用
IEnumerator<int>而不是var;这意味着枚举器将被装箱,但装箱和工作比没有装箱和损坏要好 -
可变结构是邪恶的™
-
确认:
L_0065: ldfld valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator`0<int32> ConsoleApplication21.Program/<NotWorking>d__1::<enumerator>5__3 L_006a: stloc.s enumerator L_006c: ldloca.s enumerator L_006e: call instance bool [mscorlib]System.Collections.Generic.List`1/Enumerator`0<int32>::MoveNext()- bleugh -
这是一个编译器错误。存储为字段的结构无关紧要。 C# 规范说这不会发生,所以这是一个错误。
标签: c# list async-await ienumerable