2015-01-20 52 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