2013-05-06 15 views
25

In base al codice this answer quando il codice utilizza le variabili locali dai metodi lambda interni, il compilatore genera classi aggiuntive che possono avere un nome come c__DisplayClass1. Ad esempio il seguente codice (completamente inutile):Cosa significa "DisplayClass" quando si chiama lambda?

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

emette il seguente stack di chiamate:

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

Nota che c'è c__DisplayClass2 lì che è un nome di una classe generata dal compilatore per tenere la variabile del ciclo.

Secondo this answerc__DisplayClass "significa"

c -> metodo anonimo classe di chiusura ("DisplayClass")

Va bene, ma cosa significa "DisplayClass" significa qui?

Che cosa "visualizza" questa classe generata? In altre parole, perché non è "MagicClass" o "GeneratedClass" o un altro nome?

+0

@PinnyM La risposta in là dice "c -> metodo anonimo classe di chiusura (" DisplayClass ")" e che in realtà non rispondi "cosa significa". – sharptooth

+0

Sì, è la classe che avvolge una chiusura anonima del metodo. Come spiegato in questo post, i nomi sono arbitrari e possono cambiare in qualsiasi momento - non ha alcun significato oltre a quello. Rivolgiti ad Eric se vuoi maggiori dettagli ... – PinnyM

+0

@PinnyM: Ok, allora la risposta è qualcosa come "questa è la cosa migliore che gli sviluppatori avrebbero potuto inventare in quel momento"? – sharptooth

risposta

24

Da an answer to a related question by Eric Lippert:

La ragione per cui una classe di chiusura si chiama "DisplayClass" è un po 'sfortunato: questo è il gergo utilizzato dal team debugger per descrivere una classe che ha comportamenti speciali quando vengono visualizzati nel debugger . Ovviamente non vogliamo visualizzare "x" come campo di una classe con un nome impossibile quando esegui il debug del tuo codice; piuttosto, vuoi che assomigli a qualsiasi altra variabile locale. Nel debugger c'è una marcia speciale da gestire per fare questo tipo di classe di visualizzazione. Probabilmente avrebbe dovuto essere chiamato "ClosureClass" per facilitare la lettura del disassemblaggio.

7

È possibile ottenere alcune informazioni dall'origine del compilatore C# come disponibile dalla distribuzione SSCLI20, sottodirectory csharp/sccomp. La ricerca del codice per "display" fornisce la maggior parte dei colpi nel file di codice sorgente fncbind.cpp. Lo vedrai usato nei simboli del codice e nei commenti.

I commenti suggeriscono fortemente che si trattava di un termine utilizzato internamente dal team, probabilmente già durante le riunioni di progettazione. Questo è un codice vintage .NET 2.0, non c'era ancora molta riscrittura del codice in corso. Solo iteratori e metodi anonimi, entrambi implementati in modi molto simili. Il termine "display class" è spostato da "user class" nei commenti, un chiaro suggerimento che hanno usato il termine per indicare le classi generate automaticamente. Nessun indizio forte sul perché il "display" sia stato favorito, ho il sospetto che potrebbe avere qualcosa a che fare con queste classi che sono visibili nei metadati dell'assembly.

6

Sulla base di riflettore, DisplayClass può essere tradotto come 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; 
    } 
} 
Problemi correlati