2011-12-30 8 views
5

Capisco che le enumerazioni siano compilate come costanti, quindi cambiandole si ottiene un cambio di rottura. Quello che mi chiedo è perché non sono stati compilati Enum allo stesso modo in cui sono statiche le variabili readonly?Perché gli Enum sono stati compilati come costanti anziché come valori statici?

+1

I valori di enumerazione non possono essere modificati in fase di esecuzione nello stesso modo in cui non è possibile.Se fossero statici ciò implicherebbe che il loro valore potrebbe cambiare. –

risposta

6

Possono essere più efficienti dei campi, quindi non è necessario compilarli nello stesso modo quando possono essere incorporati direttamente nell'IL.

[Enum] vengono caricati nello stesso modo con cui viene caricato il valore const. Sono incorporati direttamente nel IL . I campi, d'altra parte, richiedono un'istruzione di carico sul campo (ldsfld) che influirà in qualche modo sulle prestazioni. Le enumerazioni sono quindi altrettanto veloci di const nell'uso tipico; i campi sono un po 'più lenti.

(Source)

+0

Ok, quindi è stata una decisione basata sulle prestazioni. Questo è esattamente quello che stavo cercando ... la risposta al "Perché?". –

1

Da enum (C# Reference)

Proprio come con qualsiasi costante, tutti i riferimenti a singoli valori di un'enumerazione vengono convertiti in valori numerici in fase di compilazione

Quindi mi manca qualcosa?

+0

Sì. La domanda era: "Perché vengono compilati come costanti anziché come readonlys statici?" ... Fondamentalmente, quale è stata la decisione di progettazione di renderli costanti letterali invece di readonlys statico? –

+0

@my, Se non sbaglio readonly può essere impostato su Instantiation, e non è lo stesso di costanti che non possono essere impostate su Instantiation –

8

Entrambe le risposte fornite sono tecnicamente corrette ma mancano le spiegazioni per le costanti differantianti con statica (in sola lettura). In C#, costanti sono sempre più veloce di sola lettura e il motivo è molto semplice e esprime al meglio con un piccolo esempio di codice:

const int MyConstant = 10; 
static readonly int MyReadonly = 20; 

static void Main() 
{ 
    int result = MyConstant + MyReadonly; 
    // the above statement will be resolved to: 
    // int result = 10 + MyReadonly 
} 

In fase di compilazione, il compilatore sostituisce tutti i riferimenti a una costante con il valore effettivo di tale costante . È in grado di farlo perché una costante deve essere predefinita al momento della compilazione. Questo differisce dai valori statici di readonly che, sebbene statici, sono effettivamente risolti in fase di runtime. Prendiamo il seguente esempio:

static readonly Encoding = Encoding.GetEncoding("GB2132"); 

v'è alcun modo per il compilatore per sapere se GB2132 esiste realmente sulla macchina su cui questo codice è destinato per l'esecuzione. L'unico modo per risolvere questo valore è in fase di runtime. Statico assicura che il valore stesso non sia vincolato alla durata di un'istanza e garantisce solo che il valore può essere impostato una sola volta. Non c'è modo per il compilatore di sostituire i riferimenti a questo campo in fase di compilazione poiché il valore semplicemente non può essere conosciuto.

Logicamente, solo i tipi primitivi possono essere contrassegnati come costanti.

Ora in caso di enumerazione, è molto semplice. Le enumerazioni non sono altro che valori interi con un'etichetta. Così il seguente codice:

enum MyEnum 
{ 
    First, 
    Second, 
    Third 
} 

static void Main() 
{ 
    MyEnum test = MyEnum.First; 

    if (test == MyEnum.Second) 
    { 
     // whatever 
    } 
} 

sarà risolta dal compilatore per:

const int MyEnum_First = 0; 
const int MyEnum_Second = 1; 
const int MyEnum_Third = 2; 

static void Main() 
{ 
    int test = MyEnum_First; 

    if (test == MyEnum_Second) 
    { 
     // whatever 
    } 
} 

che a sua volta significa che i riferimenti effettivi ai campi costanti può essere sostituito con il valore noto al momento della compilazione, rendendo la versione finale del codice:

static void Main() 
{ 
    int test = 0; 

    if (test == 1) 
    { 
     // whatever 
    } 
} 
+0

Spiegazione impressionante, tizio – ivowiblo

+0

Sì, ma la domanda non era il motivo per cui Enums sta cambiando i cambiamenti, ma perché Microsoft ha scelto di compilarli come costanti anziché come campi statici di sola lettura. Avrebbero potuto fare in modo che il compilatore andasse in entrambi i modi, la domanda era: perché andavano con le costanti, invece, quando quello sarebbe stato un cambiamento decisivo, e qualcuno l'ha risposto ... semplicemente per i guadagni in termini di prestazioni. –

Problemi correlati