2012-05-24 10 views
13

Qual è il punto di avere '0' come valore predefinito per enum in C#? Se io dichiaro enumerazione che inizia con un numero diverso:Perché il valore enum predefinito è 0 e non quello minimo?

enum Color 
{ 
    Blue = 1, 
    Green, 
    Red, 
} 

poi var color = default(Color) - mi restituirà '0'. Mi aspettavo di vedere il valore minimo, invece. Questo comportamento può causare problemi se ogni membro dell'enumerazione corrisponde a un numero specifico e "0" non è un valore valido.

+2

Perché un "valore minimo"? Perché non avere enumerazioni che contano? – BoltClock

+2

Perché dovresti iniziare i valori con qualsiasi valore diverso da 0? La maggior parte dei programmatori è abituata a usare 0 come punto di partenza durante il conteggio, ad es. come quando si lavora con gli array. Ti suggerirei di non dare nemmeno i valori delle tue enumerate a meno che tu non abbia una buona ragione per farlo. –

+0

@JesseWebb Questo è un esempio. Ma potrei dichiarare l'enumerazione, in cui ogni membro ha un valore specifico. Recentemente ho lavorato con file di un certo formato, in cui ogni voce era definita da 1, 2 o 3 valori di tag. – username

risposta

8

Possiamo ipotizzare solo circa perché un aspetto del framework .NET è stato progettato in un certo modo. Per la spiegazione più semplice, mi piacerebbe sottolineare questa osservazione da the MSDN documentation:

Un'enumerazione è un insieme di costanti denominato il cui tipo sottostante è qualsiasi tipo integrale, tranne Char. Se nessun tipo sottostante è esplicitamente dichiarato , viene utilizzato Int32.

Si noti che un'enumerazione .NET è essenzialmente un'estensione di un tipo integrale. Il valore predefinito per i tipi interi è 0, quindi è ragionevole (anche se un po 'scomodo nei casi che hai illustrato) che le enumerazioni ereditino quel comportamento.

+0

Ma quando non utilizzo i valori 0 per le enumerazioni mi imbatto "Un'eccezione di tipo 'System.NullReferenceException' si è verificata in MyProjectName.dll ma non è stata gestita nel codice utente. Informazioni aggiuntive: Riferimento dell'oggetto non impostato su un'istanza di un oggetto." errore. Come sistemarlo? Nota: utilizzo un metodo di estensione per visualizzare le descrizioni di enum, ma non sono sicuro di come evitare l'errore nel metodo di supporto (GetDescription) definito su [questa pagina] (http://stackoverflow.com/questions/34293468/cannot- display-enum-values-on-kendo-grid/34294589? noredirect = 1 # comment56355782_34294589) –

+1

@Christof Non posso rispondere a questa domanda senza vedere il tuo codice, ma l'eccezione che stai descrivendo suggerisce che una variabile sia impostata a 'null 'inaspettatamente. Ecco cosa cercare durante il debug. –

+0

Ok, grazie. Ho risolto il problema utilizzando il metodo GetDescription() su [Enum ToString con stringhe user-friendly] (http://stackoverflow.com/questions/479410/enum-tostring-with-user-friendly-strings). –

0

Il punto è Probabilmente ha un valore intero meno positivo possibile.

Perché meno positivo?

Per essere in grado di trattare enum con funzionamento bit-shift correttamente.

Sto parlando naturalmente del valore predefinito, che può essere modificato dallo sviluppatore.

12

Il valore predefinito per tutti i tipi di valore (incluso enum) è bit a bit 0. Di conseguenza, significa che 0 è sempre possibile valore per enum anche se non è definito esplicitamente.

Ecco le specifiche: Default values table

EDIT: per maggiori dettagli si MSDN per i tipi di enumerazione - enum

enum è tipo che è speciale in un modo in cui il 'sorta-di deriva da altra tipo di valore (che normalmente non è possibile), ma si comporta come un tipo di valore del suo tipo di supporto. Un enum può usare solo alcuni valori interi come tipo di supporto.

Nota: come @archil indica che il valore enum può contenere qualsiasi valore del tipo di backup, indipendentemente dall'elenco di costanti enumerate nell'enum stesso. Per le enumerazioni contrassegnate con "FlagsAttribute" normalmente si prevede questo comportamento, ma per le normali enumerazioni potrebbe non essere intuitivo.

+1

Ho letto il documento grazie, ma la domanda è perché così. L'enumerazione non dovrebbe contenere solo valori dichiarati nel codice? Ora devo creare l'elemento 0 predefinito e controllare sempre che non sia quell'elemento. E non posso sicuramente aspettarmi che il membro di enum sia sempre quello che ho fornito. Suppongo sia stato facile implementarlo in questo modo in C#. – username

+1

No. Un enum può contenere qualsiasi valore come tipo di supporto (int di default). Per lo stesso motivo ha il valore predefinito come tipo di supporto, se non diversamente specificato. Utilizzare la funzione Enum.IsDefined (valore) per convalidare i parametri enum di input. –

+1

Hmm, avrei dovuto leggere questa risposta prima di postare la mia. Tuttavia, questo è un po 'troppo generalizzato: le enumerazioni non sono tipi di valore, ma i loro tipi di supporto sono. Un enum non può usare * qualsiasi * valore come tipo di supporto, solo valori interi. Vale la pena chiarire questi punti. :) –

7

Esiste sempre la possibilità per enum di avere un valore inesistente. Ecco perché esiste Enum.IsDefined Method.

Il valore predefinito di un'enumerazione E è il valore prodotto dall'espressione (E) 0.

+0

@BoltClock ma come ho controllato, ho modificato la mia risposta per una definizione più corretta – archil

+0

Stai dicendo che l'enum può avere qualcos'altro tranne 0 se non è dichiarato nel codice? – username

0

Non so perché ma ...

Ecco il doc su C# enum: http://msdn.microsoft.com/en-us/library/sbbt4032.aspx

Enumerators possibile utilizzare inizializzatori per ignorare i valori di default, come mostrato nel seguente esempio.

giorni enum {Sat = 1, dom, lun, mar, mer, gio, ven};

In questa enumerazione, la sequenza di elementi è forzata per iniziare da 1 anziché 0. Tuttavia, è consigliabile includere una costante con valore 0. Per ulteriori informazioni, see Enumeration Types (C# Programming Guide).

Si consiglia di includere sempre un valore enum segnaposto che corrisponde al valore 0 altrimenti si possono incontrare problemi. Potresti chiamare questo valore enum come Undefined o Default o qualcosa del genere.

Come ho già detto nel mio commento alla tua domanda, la mia raccomandazione sarebbe quella di non utilizzare i valori per le tue enumerazioni a tutti a meno che tu non abbia una buona ragione per farlo. Se è necessario, seguire lo MSDN Programming Guide for Enumeration Types

1

Perché 0 è il valore enum predefinito? Facilità di implementazione runtime. Il valore predefinito di qualsiasi tipo di valore è bit a bit 0 e, presumibilmente, un riferimento null è rappresentato da bitwise 0. Pertanto, per costruire inizialmente un oggetto con i suoi valori predefiniti, è sufficiente conoscere la sua dimensione; il runtime non ha bisogno di conoscere o elaborare nulla sulla struttura dell'oggetto. Allo stesso modo, il costruttore del tipo di valore predefinito può semplicemente riempire un intervallo di memoria con zero.

Piaccia o no, è così che è. Quello che dobbiamo fare in risposta è quando progettiamo un enum, qualunque nome sia un valore predefinito adatto, dargli il valore 0. Se non c'è un valore predefinito adatto, i tuoi metodi che accettano un enum come parametro potrebbero verificare che sia impostato correttamente, per esempio

void ProcessColor(Color c) { 
    if (c == 0) 
     throw new ArgumentException("Color is not set", "c"); 
    //... 
} 
+0

Sì, questo è quello che devo fare ora, per verificare se non è 0. Tuttavia, è meglio includere un valore predefinito di 0 in enum per evitare eventuali incoerenze implicite. Grazie. – username

0

enum è int (per impostazione predefinita). Le enumerazioni sono intese dal punto di vista umano per il nostro codice sorgente, ma quando il programma viene compilato, non c'è enum, solo int s. Il valore predefinito per int è 0.

Questo codice:

public enum test { One, Two, Three } 

var x = test.One; 
var y = 0; 

diventa presente in IL:

IL_0001: ldc.i4.0 
IL_0002: stloc.0  
IL_0003: ldc.i4.0  
IL_0004: stloc.1 

Così, come potrebbe un int avere un valore predefinito di 1 (come da voi richiesto) in alcuni casi, ma non in altri?

3

Come è stato affermato finora in più risposte, il valore "predefinito" per qualsiasi struttura dati a dimensione fissa è 0. La dimensione della memoria delle strutture è impostata su zero e viene considerata "predefinita". Ora, se si desidera definire il proprio valore "predefinito" per un enum, si hanno più opzioni.Il modo più semplice sarebbe quella di scrivere la propria funzione per darvi un "enum valida minimo"

private E GetDefaultEnum<E>() 
{ 
    return (E)(Enum.GetValues(typeof(E)).Cast<E>().Min<E>()); 
} 

Usage:

enum Color 
{ 
    Blue = 1, 
    Green, 
    Red, 
} 

Color defaultColor = GetDefaultEnum<Color>(); 
MessageBox.Show(defaultColor.ToString()); // "Blue" 

È possibile, ovviamente, alterare come si determina un valore di "default", ma in questo modo sembra più adatto alle tue esigenze.

Problemi correlati