2015-01-20 59 views
0

类似:How do closures work behind the scenes? (C#)C#关闭。它如何改变结构类型的变量?

假设我们有代码:

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

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

我们将看到的结果 “”。

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

那么这个类看起来像(伪):

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()); 
} 

它很清楚它如何改变实例的参考类型。但它如何与结构工作?

我想它会在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专家。任何想法?

+0

你是什么意思“改变引用类型的实例”? – 2015-01-20 19:45:40

+0

同意。它说的不对。我的意思是我们通过引用改变对象。但是,如果我们在'DisplayClass1'中为'i'指定了其他的引用,它就不能正确工作(这里是我的错误,不是吗?) 正如我从Servy的答案中看到的,对于引用类型和值类型编译器都会生成相同的代码。 – 2015-01-20 20:11:20

回答

1

您的伪代码不太正确。它实际上取代了所有使用封闭类的本地字段:

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()); 
} 
+0

谢谢! 但它如何处理如果anonimous函数捕获不是局部变量,但方法参数? – 2015-01-20 19:52:14

+0

@EugenePokotilo初始化闭包类时,它会将参数中的值复制到闭包类的字段中,然后原始代码中参数的所有用法将成为闭包类相应字段的用法。 – Servy 2015-01-20 19:56:50

+0

哦))简单。谢谢! – 2015-01-20 19:59:57