2009-07-22 41 views
54

Ho una classe con una proprietà che è un enumValore iniziale di un Enum

L'enum è

/// <summary> 
/// All available delivery actions 
/// </summary> 
public enum EnumDeliveryAction 
    { 
    /// <summary> 
    /// Tasks with email delivery action will be emailed 
    /// </summary> 
    Email, 

    /// <summary> 
    /// Tasks with SharePoint delivery action 
    /// </summary> 
    SharePoint 
    } 

Quando creo un'istanza di questa classe, in nessuna parte del codice, faccio a specificare il valore del campo enum, ma sembra essere il default del primo elemento della enumerazione, e non un valore nullo, è così che funzionano le enumerazioni? Come è possibile garantire che l'enum ottenga qualche tipo di valore nullo se non è impostato, non lo voglio come predefinito per il primo valore nell'enumerazione.

+0

Enum è un tipo di valore, al contrario di un tipo di riferimento. I tipi di riferimento saranno considerati come valori di default, mentre i tipi di valore verranno impostati come valori predefiniti. Cioè int è impostato su 0, l'ora predefinita è impostata sulla data minima, ecc. – contactmatt

risposta

103

Il valore predefinito per i tipi enum è 0 (che è, per impostazione predefinita, il primo elemento dell'enumerazione). I campi di una classe verranno inizializzati sul valore predefinito.

Se avete bisogno di rappresentare uno sconosciuto valore nel enum, è possibile aggiungere un elemento Unknown con valore 0. In alternativa, si potrebbe dichiarare il campo come Nullable<MyEnum> (MyEnum?).

+0

Quindi è necessario iniziare il primo valore enumerato con 1? –

+0

Aggiornamento della risposta per riflettere questo. –

+1

A meno che non si desideri che il valore predefinito non sia definito. Sarà comunque impostato su un valore zero, che, se l'enumerazione non ha un membro con valore zero, sarà un valore non valido. –

8

Enum sono un tipo di valore, come ints. È necessario renderlo nullable in modo da non eseguire l'impostazione predefinita per il membro enum primo (o definito da 0).

public class MyClass 
{ 
    public EnumDeliveryAction? DeliveryAction { get; set;} 
} 
+1

o aggiungi un membro non definito: public enum EnumDeliveryAction {Undefined = 0, Email = 1, Sharepoint = 2} –

+0

Puoi anche utilizzare Nullable – Polaris878

+1

Polaris: 'Nullable ' è identico a 'T?'. –

7

I campi Enum sono inizializzati come zero; un se non si specificano i valori in un enum, iniziano da zero (Email = 0, SharePoint=1, ecc.).

Pertanto, per impostazione predefinita, qualsiasi campo che si inizializza da solo sarà Email. È relativamente comune aggiungere None=0 per tali casi o in alternativa utilizzare Nullable<T>; vale a dire

/// <summary> 
/// All available delivery actions 
/// </summary> 
public enum EnumDeliveryAction 
{ 
    /// <summary> 
    /// Not specified 
    /// </summary> 
    None, 

    /// <summary> 
    /// Tasks with email delivery action will be emailed 
    /// </summary> 
    Email, 

    /// <summary> 
    /// Tasks with SharePoint delivery action 
    /// </summary> 
    SharePoint 
} 

Si dovrebbe anche essere sicuri di non trattare la vostra ultima previsto valore come default; cioè

switch(action) { 
    case EnumDeliveryAction.Email; RunEmail(); break; 
    default: RunSharePoint(); break; 
} 

questo dovrebbe essere:

switch(action) { 
    case EnumDeliveryAction.Email; RunEmail(); break; 
    case EnumDeliveryAction.SharePoint; RunSharePoint(); break; 
    default: throw new InvalidOperationException(
      "Unexpected action: " + action); 
} 
0

L'aproach tradizionale per aggiungere un valore nullo a valori che non hanno generalmente uno è quello di dichiarare la variabile come tipo nullable, cioè:

EnumDeliveryAction? action=null; 
0

Suggerirei di avere un valore di None = 0 come primo valore enum. Rendilo esplicito, quindi sai per certo qual è il suo valore.

1

È possibile avviare l'enumerazione a qualsiasi valore (ad esempio 1), ma quando rappresentano un valore di ricerca in un database, generalmente si desidera che corrispondano.

Generalmente dichiaro il primo Enum come None (= 0) quando ha senso farlo, come da linee guida .Net Framework Design.

6

Le best practice (come consigliato dall'analisi del codice) prevedono sempre un valore predefinito nelle enumerazioni, che rappresentano un valore non impostato.

Quindi nel tuo caso, si potrebbe avere:

public enum EnumDeliveryAction 
    { 

    /// <summary> 
    /// Default value 
    /// </summary> 
    NotSet, 

    /// <summary> 
    /// Tasks with email delivery action will be emailed 
    /// </summary> 
    Email, 

    /// <summary> 
    /// Tasks with SharePoint delivery action 
    /// </summary> 
    SharePoint 
    } 

Per inciso, non si deve anteporre il nome del enum con Enum. Potresti considerare di passare a:

public enum DeliveryAction; 
+0

Non sono così sicuro di essere d'accordo con l'aggiunta di un enum membro "non definito" in .Net poiché questo è ciò che vuol dire per definizione - sconosciuto. Sembra ridondante ridefinire null in ogni enum che crei. –

+1

Mi sembra che avere un valore predefinito nel tuo enum sia una pratica molto migliore rispetto all'utilizzo di enumerazioni nullable. – Tim

0

Per impostazione predefinita, solo i tipi di riferimento sono tipi annullabili. Se vuoi una variabile per consentire i null devi definirla come nullable usando "?" carattere (per questo è necessario C# 2.0 o superiore).

enum MyEnum 
{ 
    ValueOne, 
    ValueTwo 
} 

e nella tua classe

MyEnum? myvariable = null; 
+0

Penso che tu intenda che solo * i tipi di riferimento * sono annullabili per impostazione predefinita, poiché entrambi i tipi di riferimento e valore sono considerati oggetti in .NET – PatrickJ

+0

Sì, questo è ciò che intendevo: D –

3

enumerazioni sono tipi di valore. I tipi di valore non può essere nullo e vengono inizializzati a 0.

Anche se il vostro enum non dispone di un 0, variabili enum vengono inizializzati a 0.

public enum SomeEnum 
{ 
    A = 1, 
    B = 2 
} 

(in seguito)

SomeEnum x = default(SomeEnum); 
Console.WriteLine(x); 

Uscite - 0


Alcune answerers stanno sostenendo con Nullable<T> per abbinare il vostro i aspettative di nazionalizzazione Con questo consiglio dato che Nullable<T> è ancora un tipo di valore e ha semantica diversa rispetto ai tipi di riferimento. Ad esempio, non genererà mai un'eccezione di riferimento null (non è un riferimento).

SomeEnum? x = default(SomeEnum?); 

if (x == null) 
{ 
    Console.WriteLine("It's null!"); 
} 
if (x > SomeEnum.B) 
{ 
} 
else 
{ 
    Console.WriteLine("This runs even though you don't expect it to"); 
} 
0

mio C insegnante ++ in un college (11 anni fa) mi ha detto che il linker sostituisce enum con il loro tipo effettivo:

typedef static const int enum;

Così, ogni volta che scrivere qualcosa di simile enum MY_VAL = 5;, si potrebbe facilmente sostituire con static const int MY_VAL = 5; (ma ciò rende il codice più lungo ...).

In ogni caso, il valore di default di qualsiasi int è 0.