2009-10-27 9 views
6

C# 3 (Visual Studio 2008) ha introdotto una modifica della lingua (http://msdn.microsoft.com/en-us/library/cc713578.aspx, vedere la modifica 12) che consente di convertire qualsiasi zero letterale in un Enum. Questo sembra strano in molti modi. Qualcuno sa perché questo fa parte delle specifiche? Perché non letterale? O sette? Perché lo zero è speciale? E fa alcune scelte di risoluzione di sovraccarico molto controintuitive. Per esempio.Perché C# 3 consente la conversione implicita dello zero letterale (0) in qualsiasi Enum?

function string F(object o) { return o.ToString(); } 
function string F(DbType t) { return t.ToString(); } 
int i = 0; 
F((long)0) == "String" // would have been "0" in VS 2005 
F(0) == "String" 
F(i) == "0" 

Molto confuso e una modifica introdotta intenzionalmente nella lingua. Qualche idea?

+0

Se si intende apportare una modifica così drastica a una domanda (soprattutto una che ha già votato per le risposte), sarebbe meglio, per i risponditori, i browser e l'utente, creare una nuova domanda. Avrai ora le risposte a due domande diverse, la prima delle quali probabilmente i browser occasionali non vedranno mai nella cronologia delle modifiche. – joshperry

+0

e, come per magia, la domanda è stata rimandata alla sua originale forma fuorviante! bisogna notare che il campione dato non è infranto in VS 2008. Farò quel cambiamento e vedrò se si attacca ... –

risposta

10

C# ha sempre consentito la conversione implicita del letterale 0 a qualsiasi valore Enum. Ciò che è cambiato è come la regola viene applicata ad altre espressioni costanti. È stato creato per essere più coerente e consentire a qualsiasi espressione costante che valuta 0 di essere implicitamente convertibile in enum.

L'esempio fornito produce lo stesso comportamento in tutte le versioni di C#.

Ecco un esempio di comportamento modificato (direttamente dal linked documentation)

public enum E 
{ 
    Zero = 0, 
    One = 1, 
} 

class A 
{ 
    public static A(string s, object o) 
    { System.Console.WriteLine("{0} => A(object)", s); } 

    public static A(string s, E e) 
    { System.Console.WriteLine("{0} => A(Enum E)", s); } 

    static void Main() 
    { 
     A a1 = new A("0", 0); 
     A a3 = new A("(int) E.Zero", (int) E.Zero); 
    } 
} 

Visual C# 2005 Uscita:

 
0 => A(Enum E) 
(int) E.Zero => A(object)

Visual C# 2008 Uscita:

 
0 => A(Enum E) 
(int) E.Zero => A(Enum E)
+0

Ah, un buon punto. L'esempio della nostra applicazione era in realtà il punto in cui il programmatore usava (long) 0. Forse in una versione precedente che non attivava la regola di 'espressione costante'. La domanda è ancora valida: perché se nessun altro intero è implicitamente convertibile in un Enum è zero? –

+0

@Sebastian, non sono sicuro su questo punto. Probabilmente c'è un motivo linguistico molto interessante per cui, spero, Eric sarà in futuro a commentarlo. – JaredPar

+0

Un'espressione costante è qualsiasi espressione che può essere determinata in fase di compilazione per ottenere un valore costante (il valore del risultato dell'espressione potrebbe essere sostituito nel codice sorgente senza effetti collaterali). In VS 2005 solo gli zeri "letterali" sono stati implicitamente convertiti in enumerazioni, in> = VS 2008 qualsiasi "espressione costante" che viene valutata a zero verrà convertita implicitamente. – joshperry

1

È stato consentito dalla versione 1.0. È il valore predefinito di un enum.

"Un letterale 0 è implicitamente convertibile a qualsiasi tipo enum. In Visual C# 2005 e versioni precedenti del compilatore, ci sono anche alcune costanti espressioni che restituiscono 0 che convertire implicitamente a qualsiasi enum tipo, ma la regola che determina quale di queste espressioni sono convertibile non è chiaro. In Visual C# 2008, tutte le espressioni costanti che sono uguali a 0 può essere implicitamente convertito a qualsiasi tipo enum."

3

Direi che è perché 0 è considerato il "Valore predefinito" delle enumerazioni.

C# (parola chiave predefinita è stata introdotta in C# 2,0)

enum DbType { 
    Unspecified, 
    SqlServer 
} 

DbType t; 
int i = 0; 

Console.WriteLine(t == i); 
Console.WriteLine(i == default(DbType)); 

Uscite:

True 
True 
+0

Immagino che sia praticamente proprio perché 'default (T)' non esisteva in 1.0, e non volevano avere un'incoerenza nella lingua in cui si poteva ottenere la variabile enum predefinita inizializzata a '0' implicitamente, ma non esplicitamente (senza un cast). –

+0

@Pavel Minaev - Mi piace questa teoria. –

0

"Il tipo di base predefinito degli elementi di enumerazione è int. Per impostazione predefinita, il primo enumeratore ha il valore 0 e il valore di ciascun enumeratore successivo è aumentato di 1. "- Questo è da MSDN notes for 1.1 framework, quindi è sempre stato il caso

0

Come altri hanno già detto, 0 è l'impostazione predefinita enum.Provate a pensare a enumerazioni come segue (in modo più esplicito):

public enum HairColor 
{ 
    Blonde   = 0x0000; 
    Brunett   = 0x0001; 
    Red    = 0x0002; 
    StrawberryBlonde = 0x0004; 
} 

Perché non stai comportando esplicito nei tuoi valori di una data di enumerazione, C# saranno automagicamente assegnarle un valore predefinito. Se non lo si desidera, sarà necessario definire esplicitamente i valori per una determinata enumerazione.

Problemi correlati