C#封闭。它如何改变struct类型的变量?

时间:2015-01-20 19:43:10

标签: c# .net clr

类似于:How do closures work behind the scenes? (C#)

假设我们有代码:

static void Main(string[] args)
{
  int i = 100;
  Action d = () => { i++; };
  d();

  Console.WriteLine(i.ToString());  
}

我们会看到结果" 101 "。

我知道如果匿名函数捕获局部变量,它会创建一个新类,其中包含局部变量的字段和与匿名函数相关的方法。

所以这个类看起来像(伪代码):

 private class DisplayClass1
 {
     public int i;            
     public void Main(){ i++; }
 }

使用ILDasm.exe,我们看到生成的类:

enter image description here

然后程序的主要方法看起来像(伪代码):

static void Main(string[] args)
{
  int i = 100;

  //create helper class
  DisplayClass1 class1 = new DisplayClass1();
  //initialize fields
  class1.i = i;

  //crete instance of delegate
  Action d = new Action(class1.Main);

  d.Invoke();

  Console.WriteLine(i.ToString());
}

很明显它如何更改引用类型的实例。但它如何与struct一起使用?

我想它会在d.Invoke();之后再添加一行i = class1.i;(多线程的任何问题?)或者在DisplayClass1.Main中执行一些特殊操作来从堆栈访问同一个变量。 这是此方法的IL代码:

.method public hidebysig instance void  '<Main>b__0'() cil managed
{
  // Code size       16 (0x10)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  dup
  IL_0003:  ldfld      int32 ConsoleApplication3.Program/'<>c__DisplayClass1'::i
  IL_0008:  ldc.i4.1
  IL_0009:  add
  IL_000a:  stfld      int32 ConsoleApplication3.Program/'<>c__DisplayClass1'::i
  IL_000f:  ret
} // end of method '<>c__DisplayClass1'::'<Main>b__0'

我不是MSIL的专家。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您的伪代码不太对劲。它实际上用闭包类的字段替换了local的所有用法:

static void Main(string[] args)
{
  //create helper class
  DisplayClass1 class1 = new DisplayClass1();
  //initialize fields
  class1.i = 100;

  //crete instance of delegate
  Action d = new Action(class1.Main);

  d.Invoke();

  Console.WriteLine(class1.i.ToString());
}