主要内容:
1、描述出现的现像
2、分析其出现的原因
3、提示
一、看如下一段代码及结果
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 List<Action> lists = new List<Action>(); 6 for (int i = 0; i < 5; i++) 7 { 8 9 Action t = () => 10 { 11 12 Console.WriteLine(i.ToString()); 13 }; 14 lists.Add(t); 15 } 16 foreach (var t in lists) 17 { 18 t(); 19 } 20 21 Console.Read(); 22 } 23 }
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 List<Action> lists = new List<Action>(); 6 for (int i = 0; i < 5; i++) 7 { 8 int temp = i; 9 Action t = () => 10 { 11 Console.WriteLine(temp.ToString()); 12 13 }; 14 lists.Add(t); 15 } 16 foreach (var t in lists) 17 { 18 t(); 19 } 20 21 Console.Read(); 22 } 23 }
为什么加了一个临时变量就结果不一样了呢?
二、现像分析
我们查看第一段代码的il和第二段的il
1 .method private hidebysig static void Main(string[] args) cil managed 2 { 3 .entrypoint 4 // 代码大小 149 (0x95) 5 .maxstack 3 6 .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action> lists, 7 [1] class [mscorlib]System.Action t, 8 [2] class [mscorlib]System.Action 'CS$<>9__CachedAnonymousMethodDelegate1', 9 [3] class iltest.Program/'<>c__DisplayClass2' 'CS$<>8__locals3', 10 [4] bool CS$4$0000, 11 [5] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action> CS$5$0001) 12 IL_0000: nop 13 IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::.ctor() 14 IL_0006: stloc.0 15 IL_0007: ldnull 16 IL_0008: stloc.2 17 IL_0009: newobj instance void iltest.Program/'<>c__DisplayClass2'::.ctor() 18 IL_000e: stloc.3 19 IL_000f: ldloc.3 20 IL_0010: ldc.i4.0 21 IL_0011: stfld int32 iltest.Program/'<>c__DisplayClass2'::i 22 IL_0016: br.s IL_0044 23 IL_0018: nop 24 IL_0019: ldloc.2 25 IL_001a: brtrue.s IL_002b 26 IL_001c: ldloc.3 27 IL_001d: ldftn instance void iltest.Program/'<>c__DisplayClass2'::'<Main>b__0'() 28 IL_0023: newobj instance void [mscorlib]System.Action::.ctor(object, 29 native int) 30 IL_0028: stloc.2 31 IL_0029: br.s IL_002b 32 IL_002b: ldloc.2 33 IL_002c: stloc.1 34 IL_002d: ldloc.0 35 IL_002e: ldloc.1 36 IL_002f: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::Add(!0) 37 IL_0034: nop 38 IL_0035: nop 39 IL_0036: ldloc.3 40 IL_0037: dup 41 IL_0038: ldfld int32 iltest.Program/'<>c__DisplayClass2'::i 42 IL_003d: ldc.i4.1 43 IL_003e: add 44 IL_003f: stfld int32 iltest.Program/'<>c__DisplayClass2'::i 45 IL_0044: ldloc.3 46 IL_0045: ldfld int32 iltest.Program/'<>c__DisplayClass2'::i 47 IL_004a: ldc.i4.5 48 IL_004b: clt 49 IL_004d: stloc.s CS$4$0000 50 IL_004f: ldloc.s CS$4$0000 51 IL_0051: brtrue.s IL_0018 52 IL_0053: nop 53 IL_0054: ldloc.0 54 IL_0055: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::GetEnumerator() 55 IL_005a: stloc.s CS$5$0001 56 .try 57 { 58 IL_005c: br.s IL_006f 59 IL_005e: ldloca.s CS$5$0001 60 IL_0060: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action>::get_Current() 61 IL_0065: stloc.1 62 IL_0066: nop 63 IL_0067: ldloc.1 64 IL_0068: callvirt instance void [mscorlib]System.Action::Invoke() 65 IL_006d: nop 66 IL_006e: nop 67 IL_006f: ldloca.s CS$5$0001 68 IL_0071: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action>::MoveNext() 69 IL_0076: stloc.s CS$4$0000 70 IL_0078: ldloc.s CS$4$0000 71 IL_007a: brtrue.s IL_005e 72 IL_007c: leave.s IL_008d 73 } // end .try 74 finally 75 { 76 IL_007e: ldloca.s CS$5$0001 77 IL_0080: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action> 78 IL_0086: callvirt instance void [mscorlib]System.IDisposable::Dispose() 79 IL_008b: nop 80 IL_008c: endfinally 81 } // end handler 82 IL_008d: nop 83 IL_008e: call int32 [mscorlib]System.Console::Read() 84 IL_0093: pop 85 IL_0094: ret 86 } // end of method Program::Main
1 .method private hidebysig static void Main(string[] args) cil managed 2 { 3 .entrypoint 4 // 代码大小 127 (0x7f) 5 .maxstack 3 6 .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action> lists, 7 [1] int32 i, 8 [2] class [mscorlib]System.Action t, 9 [3] class iltest.Program/'<>c__DisplayClass1' 'CS$<>8__locals2', 10 [4] bool CS$4$0000, 11 [5] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action> CS$5$0001) 12 IL_0000: nop 13 IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::.ctor() 14 IL_0006: stloc.0 15 IL_0007: ldc.i4.0 16 IL_0008: stloc.1 17 IL_0009: br.s IL_0033 18 IL_000b: newobj instance void iltest.Program/'<>c__DisplayClass1'::.ctor() 19 IL_0010: stloc.3 20 IL_0011: nop 21 IL_0012: ldloc.3 22 IL_0013: ldloc.1 23 IL_0014: stfld int32 iltest.Program/'<>c__DisplayClass1'::temp 24 IL_0019: ldloc.3 25 IL_001a: ldftn instance void iltest.Program/'<>c__DisplayClass1'::'<Main>b__0'() 26 IL_0020: newobj instance void [mscorlib]System.Action::.ctor(object, 27 native int) 28 IL_0025: stloc.2 29 IL_0026: ldloc.0 30 IL_0027: ldloc.2 31 IL_0028: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::Add(!0) 32 IL_002d: nop 33 IL_002e: nop 34 IL_002f: ldloc.1 35 IL_0030: ldc.i4.1 36 IL_0031: add 37 IL_0032: stloc.1 38 IL_0033: ldloc.1 39 IL_0034: ldc.i4.5 40 IL_0035: clt 41 IL_0037: stloc.s CS$4$0000 42 IL_0039: ldloc.s CS$4$0000 43 IL_003b: brtrue.s IL_000b 44 IL_003d: nop 45 IL_003e: ldloc.0 46 IL_003f: callvirt instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<class [mscorlib]System.Action>::GetEnumerator() 47 IL_0044: stloc.s CS$5$0001 48 .try 49 { 50 IL_0046: br.s IL_0059 51 IL_0048: ldloca.s CS$5$0001 52 IL_004a: call instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action>::get_Current() 53 IL_004f: stloc.2 54 IL_0050: nop 55 IL_0051: ldloc.2 56 IL_0052: callvirt instance void [mscorlib]System.Action::Invoke() 57 IL_0057: nop 58 IL_0058: nop 59 IL_0059: ldloca.s CS$5$0001 60 IL_005b: call instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action>::MoveNext() 61 IL_0060: stloc.s CS$4$0000 62 IL_0062: ldloc.s CS$4$0000 63 IL_0064: brtrue.s IL_0048 64 IL_0066: leave.s IL_0077 65 } // end .try 66 finally 67 { 68 IL_0068: ldloca.s CS$5$0001 69 IL_006a: constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<class [mscorlib]System.Action> 70 IL_0070: callvirt instance void [mscorlib]System.IDisposable::Dispose() 71 IL_0075: nop 72 IL_0076: endfinally 73 } // end handler 74 IL_0077: nop 75 IL_0078: call int32 [mscorlib]System.Console::Read() 76 IL_007d: pop 77 IL_007e: ret 78 } // end of method Program::Main
就是相当于这种代码
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 List<Action> lists = new List<Action>(); 6 TempClass tc = new TempClass(); 7 8 for ( tc.i = 0; tc.i < 5; tc.i++) 9 { 10 Action t = tc.FuncWrite; 11 lists.Add(t); 12 } 13 foreach (var t in lists) 14 { 15 t(); 16 } 17 18 Console.Read(); 19 } 20 } 21 class TempClass 22 { 23 public int i; 24 public void FuncWrite() 25 { 26 Console.WriteLine(i.ToString()); 27 } 28 29 }
说一个查看il 进入命令行,ildasm
理论分析以后补上。