C# 闭包对像

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 闭包对像相关的知识,希望对你有一定的参考价值。

主要内容:

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     }
View Code
技术分享
技术分享
 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     }
View Code

技术分享

为什么加了一个临时变量就结果不一样了呢?

二、现像分析

我们查看第一段代码的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
View Code
技术分享
技术分享
 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
View Code
技术分享
就是相当于这种代码
技术分享
 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     }
View Code

说一个查看il 进入命令行,ildasm

理论分析以后补上。

 

 

 

 

以上是关于C# 闭包对像的主要内容,如果未能解决你的问题,请参考以下文章

使用C#操作Oracle Spatial的SDO_GEOMETRY对像(读取和写入)

Spark闭包与序列化

js中的闭包和c#中的闭包

C#中的闭包和意想不到的坑

C# 最有用的(自定义)代码片段是啥? [关闭]

c#代码片段快速构建代码