2013-05-06 121 views
25

根據this answer,當代碼使用lambda方法內部的局部變量時,編譯器將生成可以具有名稱的額外類,如c__DisplayClass1。例如,下面的(完全無用的)代碼:調用lambda時,「DisplayClass」名稱的含義是什麼?

class Program 
{ 
    static void Main() 
    { 
     try { 
      implMain(); 
     } catch (Exception e) { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

    static void implMain() 
    { 
     for (int i = 0; i < 10; i++) { 
      invoke(() => { 
       Console.WriteLine(i); 
       throw new InvalidOperationException(); 
      }); 
     } 
    } 
    static void invoke(Action what) 
    { 
     what(); 
    } 
} 

輸出以下調用堆棧:

System.InvalidOperationException 
at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0() 
at ConsoleApplication1.Program.invoke(Action what) 
at ConsoleApplication1.Program.implMain() 
at ConsoleApplication1.Program.Main() 

。注意,在有c__DisplayClass2其是由編譯器產生的一類名來保存循環變量。

this answerc__DisplayClass 「是指」

Ç - >匿名方法closure類( 「DisplayClass」)

好了,但什麼是 「DisplayClass」 這裏的意思?

這是什麼產生類「顯示」?換句話說,爲什麼它不是「MagicClass」或「GeneratedClass」或任何其他名稱?

+0

@PinnyM在那裏回答說 「C - >匿名方法closure類(」 DisplayClass 「)」,而並沒有真正的回答「它是什麼意思」。 – sharptooth 2013-05-06 15:29:12

+0

是的,它是封裝匿名方法閉包的類。正如那篇文章所解釋的那樣,這些名字是隨意的,隨時都可以改變 - 除此之外,它沒有任何意義。如果你想了解更多細節,大聲呼叫Eric ... – PinnyM 2013-05-06 15:34:10

+0

@PinnyM:好的,答案也是這樣的:「那是開發者可以在那個時候發明的最好的東西」? – sharptooth 2013-05-06 15:35:06

回答

24

an answer to a related question by Eric Lippert

的原因,封閉類被稱爲「DisplayClass」是有點可惜:這是使用調試器開發團隊來描述在調試器中顯示時有特殊的行爲一類術語。顯然,我們不希望在調試代碼時將「x」顯示爲不可能命名的類的字段;相反,你希望它看起來像任何其他局部變量。調試器中有特殊的裝置來處理這種顯示類。它可能應該被稱爲「ClosureClass」,以便更易於閱讀反彙編。

7

您可以從SSCLI20發行版csharp/sccomp子目錄中的C#編譯器源獲得一些信息。在代碼中搜索「display」會在fncbind.cpp源代碼文件中提供大部分匹配。您會看到它在代碼符號以及註釋中使用。

這些意見強烈表明,這是一個團隊內部使用的術語,可能早在設計會議上。這是.NET 2.0復古代碼,還沒有很多代碼重寫。只是迭代器和匿名方法,都以非常相似的方式實現。術語「顯示類」與註釋中的「用戶類」偏移,這是一個明確的提示,即他們使用該術語來表示自動生成的類。沒有強烈的暗示爲什麼「顯示」被青睞,我懷疑它可能與這些類在程序集的元數據中可見有關。

6

基於反射,DisplayClass可譯爲CompilerGeneratedClass

[CompilerGenerated] 
private sealed class <>c__DisplayClass16b 
{ 
// Fields 
public MainForm <>4__this; 
public object sender; 

// Methods 
public void <cmdADSInit_Click>b__16a() 
    { 
    ADS.Initialize(); 
    this.<>4__this._Sender = this.sender; 
    this.<>4__this.SelectedObject = ADS.Instance; 
    } 
} 
相關問題