欢迎光临

木子屋

标题: 通过MSIL看foreach循环

作者: dnawo

日期: 2010-05-14 10:01 AM

分类: Web编程

内容: 复制内容到剪贴板 程序代码static void Main(string[] args)
{
string[] names = new string[] { "zhang", "li", "wang" };
foreach (string name in names)
Console.WriteLine(name);
Console.ReadKey();
}
对应的MSIL代码为：
复制内容到剪贴板 程序代码.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 80 (0x50)
.maxstack 3
.locals init ([0] string[] names,
[1] string name,
[2] string[] CS$0$0000,
[3] string[] CS$6$0001,
[4] int32 CS$7$0002,
[5] bool CS$4$0003)
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: newarr [mscorlib]System.String
IL_0007: stloc.2
IL_0008: ldloc.2
IL_0009: ldc.i4.0
IL_000a: ldstr "zhang"
IL_000f: stelem.ref
IL_0010: ldloc.2
IL_0011: ldc.i4.1
IL_0012: ldstr "li"
IL_0017: stelem.ref
IL_0018: ldloc.2
IL_0019: ldc.i4.2
IL_001a: ldstr "wang"
IL_001f: stelem.ref
IL_0020: ldloc.2
IL_0021: stloc.0
IL_0022: nop
IL_0023: ldloc.0
IL_0024: stloc.3
IL_0025: ldc.i4.0
IL_0026: stloc.s CS$7$0002
IL_0028: br.s IL_003c
IL_002a: ldloc.3
IL_002b: ldloc.s CS$7$0002
IL_002d: ldelem.ref
IL_002e: stloc.1
IL_002f: ldloc.1
IL_0030: call void [mscorlib]System.Console::WriteLine(string)
IL_0035: nop
IL_0036: ldloc.s CS$7$0002
IL_0038: ldc.i4.1
IL_0039: add
IL_003a: stloc.s CS$7$0002
IL_003c: ldloc.s CS$7$0002
IL_003e: ldloc.3
IL_003f: ldlen
IL_0040: conv.i4
IL_0041: clt
IL_0043: stloc.s CS$4$0003
IL_0045: ldloc.s CS$4$0003
IL_0047: brtrue.s IL_002a
IL_0049: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_004e: pop
IL_004f: ret
} // end of method Program::Main
下边我们做些简单的分析
复制内容到剪贴板 程序代码.locals init ([0] string[] names,
[1] string name,
[2] string[] CS$0$0000,
[3] string[] CS$6$0001,
[4] int32 CS$7$0002,
[5] bool CS$4$0003)
我们在C#代码中只声明了两个局部变量names和name，但在MSIL中多出了4个。
复制内容到剪贴板 程序代码IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: newarr [mscorlib]System.String
IL_0007: stloc.2
IL_0008: ldloc.2
IL_0009: ldc.i4.0
IL_000a: ldstr "zhang"
IL_000f: stelem.ref
IL_0010: ldloc.2
IL_0011: ldc.i4.1
IL_0012: ldstr "li"
IL_0017: stelem.ref
IL_0018: ldloc.2
IL_0019: ldc.i4.2
IL_001a: ldstr "wang"
IL_001f: stelem.ref
IL_0020: ldloc.2
IL_0021: stloc.0
可以看到，MSIL先创建辅助字符串数组CS$0$0000，分配各元素的值，然后赋值给我们的names数组，感觉是转了一圈间接的来创建names数组，不知有什么优点？
复制内容到剪贴板 程序代码IL_0022: nop
IL_0023: ldloc.0
IL_0024: stloc.3
IL_0025: ldc.i4.0
IL_0026: stloc.s CS$7$0002
IL_0028: br.s IL_003c
IL_002a: ldloc.3
IL_002b: ldloc.s CS$7$0002
IL_002d: ldelem.ref
IL_002e: stloc.1
IL_002f: ldloc.1
IL_0030: call void [mscorlib]System.Console::WriteLine(string)
IL_0035: nop
IL_0036: ldloc.s CS$7$0002
IL_0038: ldc.i4.1
IL_0039: add
IL_003a: stloc.s CS$7$0002
IL_003c: ldloc.s CS$7$0002
IL_003e: ldloc.3
IL_003f: ldlen
IL_0040: conv.i4
IL_0041: clt
IL_0043: stloc.s CS$4$0003
IL_0045: ldloc.s CS$4$0003
IL_0047: brtrue.s IL_002a
从这段代码可以看出，foreach循环的内部其实是使用了for循环，CS$7$0002变量就相当于我们for循环中的i。让人困惑的是，这边操作的字符串数组即非CS$0$0000，也非names，又弄了个新数组CS$6$0001来用于循环，实在不解。
结论
在C#中，foreach循环的内部还是使用for循环。

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.820 ms

返回

标题: 通过MSIL看foreach循环

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.820 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 0.852 ms

返回