L_0001: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1
[mscorlib]System.Collections.Generic.IEnumerable`1::GetEnumerator()
L_0006: stloc.1
L_0007: br.s L_0016
L_0009: ldloc.1
L_000a: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1::get_Current()
L_000f: stloc.0
L_0010: ldloc.0
L_0011: call void [mscorlib]System.Console::WriteLine(int32)
L_0016: ldloc.1
L_0017: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext()
L_001c: brtrue.s L_0009
L_001e: leave.s L_002a
L_0020: ldloc.1
L_0021: brfalse.s L_0029
L_0023: ldloc.1
L_0024: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0029: endfinally
L_002a: ret
.try L_0007 to L_0020 finally handler L_0020 to L_002a
}
但是,如果使用.NET Reflector观察它的C#代码又会如何呢?
private static void DoEnumerable(IEnumerable source)
{
foreach (int i in source)
{
Console.WriteLine(i);
}
}
请注意,以上这段是由.NET Reflector从IL反编译后得到的C#代码,这简直……不是简直,是完完全全真真正正地和我们刚才写的代码一模一样!这就是.NET Reflector的强大之处,由于它意识到IL调用了IEnumerable.GetEnumerator方法,因此它就“留心”判断这个调用的“模式”是否符合一个标准的foreach,如果是,那么就会显示为一个foreach语句而不是while...MoveNext。不过,这难道不就掩盖了“事物本质”了吗?要知道我们的目标可是探究foreach的形式,既然.NET Reflector帮不了的话,我们不还是需要去观察IL吗?
刚才老赵提到,.NET Reflector在判断IL代码时发现一些标准的模式时会进行代码“优化”。那么我们能否让.NET Reflector不要做这种“优化”呢?答案是肯定的,只是需要您在.NET Reflector中进行一些简单的设置:
文章来源于领测软件测试网 https://www.ltesting.net/