• 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

    理论分析以后补上。

  • 相关阅读:
    linux系统中完整删除逻辑卷、卷组、物理劵
    linux系统中逻辑卷缩容步骤
    问题
    新的一天开始了
    Solaris的版本命名
    Sun公司的操作系统:Solaris简介
    培训经历:Awakening the Dragon Within
    大本计算机专业该怎么学习?
    windbg 使用
    ubuntu 常用技巧
  • 原文地址:https://www.cnblogs.com/ants_double/p/5526621.html
Copyright © 2020-2023  润新知