2009-10-27 13 views
6

C# 3 (Visual Studio 2008) introdujo un cambio radical en el lenguaje (http://msdn.microsoft.com/en-us/library/cc713578.aspx, consulte el cambio 12) que permite que cualquier cero literal se convierta implícitamente en un Enum. Esto parece extraño de muchas maneras. ¿Alguien sabe por qué esto es parte de la especificación? ¿Por qué no uno literal? ¿O siete? ¿Por qué el cero es especial? Y toma algunas decisiones de resolución de sobrecarga poco intuitivas. Por ejemplo.¿Por qué C# 3 permite la conversión implícita del cero literal (0) a cualquier 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" 

Muy confuso, y un cambio brusco introducido intencionalmente al idioma. ¿Algunas ideas?

+0

Si va a hacer un cambio tan drástico en una pregunta (especialmente una que ya votó por las respuestas), sería mejor que los respondedores, los navegadores y usted creen una nueva pregunta. Ahora tendrá respuestas a dos preguntas diferentes, la primera de las cuales probablemente los navegadores casuales nunca verán en el historial de edición. – joshperry

+0

y, como si fuera magia, ¡la pregunta ha sido editada nuevamente a su forma engañosa original! se debe tener en cuenta que la muestra no se rompe en VS 2008. Voy a hacer ese cambio y ver si se pega ... –

Respuesta

10

C# siempre ha permitido la conversión implícita de la literal 0 a cualquier valor Enum. Lo que ha cambiado es cómo se aplica la regla a otras expresiones constantes. Se hizo para ser más consistente y permitir que cualquier expresión constante que se evalúe como 0 sea implícitamente convertible a una enumeración.

El ejemplo que proporcionó produce el mismo comportamiento en todas las versiones de C#.

Aquí es un ejemplo de un cambio de comportamiento (directamente desde el 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 de salida:

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

Visual C# 2008 de salida:

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

Ah, un buen punto. El ejemplo de nuestra aplicación fue en realidad donde el programador usó (largo) 0. Quizás en una versión anterior que no desencadenó la regla de 'expresión constante'. La pregunta sigue en pie: ¿por qué si ningún otro entero es implícitamente convertible en un Enum es cero? –

+0

@Sebastian, no estoy seguro en este punto. Probablemente haya un lenguaje muy interesante por lo que espero que Eric esté más tarde para comentar sobre esto. – JaredPar

+0

Una expresión constante es cualquier expresión que se puede determinar en tiempo de compilación para dar como resultado un valor constante (el valor del resultado de la expresión podría reemplazarse en el código fuente sin efectos secundarios). En VS 2005 solo los ceros "literales" se convirtieron implícitamente en enumeraciones, en> = VS 2008 cualquier "expresión constante" que se evalúe como cero se convertirá implícitamente. – joshperry

1

Ha sido permitido desde la versión 1.0. Es el valor predeterminado de una enumeración.

"Un literal 0 es convertir implícitamente a cualquier tipo de enumeración. En Visual C# 2005 y versiones anteriores del compilador, también hay algunas constantes expresiones que se evalúan como 0 que puede convertir implícitamente a cualquier enumeración tipo, pero la regla que determina cuál de estas expresiones son convertible es poco clara. En Visual C# 2008, todas las expresiones constantes que son iguales a 0 puede ser implícita convertidos a cualquier tipo de enumeración ".

3

Supongo que es porque 0 se considera el "Valor predeterminado" de enums.

C# (palabra clave predeterminada se introdujo en C# 2,0)

enum DbType { 
    Unspecified, 
    SqlServer 
} 

DbType t; 
int i = 0; 

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

Salidas:

True 
True 
+0

Me imagino que es más o menos precisamente porque 'default (T)' no existía en 1.0, y no querían tener una incoherencia en el lenguaje donde se podía obtener la variable enum predeterminada-inicializada a '0' implícitamente, pero no explícitamente (sin un molde). –

+0

@Pavel Minaev - Me gusta esta teoría. –

0

"El tipo subyacente predeterminado de los elementos enumerados es int. Por defecto, el primer enumerador tiene el valor 0, y el valor de cada enumerador sucesivo se incrementa en 1. "- Esto es de MSDN notes for 1.1 framework, por lo que siempre ha sido el caso.

0

Como otros han mencionado, 0 es el valor predeterminado enum.Trate de pensar en las enumeraciones de la siguiente manera (de una manera más explícita):

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

Debido a que usted no está siendo explícito en sus valores de una enumeración dada, C# automágicamente asignarle un valor predeterminado. Si no quiere eso, entonces tendrá que definir explícitamente los valores para una enumeración dada.

Cuestiones relacionadas