2009-06-04 17 views
12

¿Hay alguna diferencia en si me inicializar una variable entera como:C# variable de inicialización Pregunta

int i = 0; 
int i; 

¿El compilador o CLR tratar esto como la misma cosa? IIRC, creo que ambos son tratados como la misma cosa, pero parece que no puedo encontrar el artículo.

+11

_Fields_ siempre se inicializan automáticamente al valor predeterminado del tipo de campo, que en el caso de int es cero. Los campos se consideran definitivamente asignados; puedes leer sus contenidos incluso antes de una tarea explícita. _Locales_ no se consideran definitivamente asignados; se requiere que haga algo que le asigna el valor de un local antes de que se lea su contenido. Consulte la sección "asignación definitiva" de la especificación C# para más detalles. –

Respuesta

6

Miré a la IL (usando ildasm) y es cierto que solo el conjunto int a 0 está realmente configurado a 0 en el constructor.

public class Class1 
{ 
    int setToZero = 0; 
    int notSet; 
} 

Genera:

.method public hidebysig specialname rtspecialname 
     instance void .ctor() cil managed 
{ 
    // Code size  15 (0xf) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: ldc.i4.0 
    IL_0002: stfld  int32 ClassLibrary1.Class1::setToZero 
    IL_0007: ldarg.0 
    IL_0008: call  instance void [mscorlib]System.Object::.ctor() 
    IL_000d: nop 
    IL_000e: ret 
} // end of method Class1::.ctor 
+0

¿Pero no es posible que el controlador de esa clase maneje la inicialización de variables para aquellas variables que no están explícitamente asignadas? –

+8

Michael: los campos se inicializan a valores predeterminados (cero) por _memory manager_, no por _constructor_. –

+0

Muchas gracias a Eric Lippert por la aclaración. Desearía haber dado crédito a una o más personas que participaron en esta discusión. Como siempre, siempre me alejo con más conocimiento de que vine aquí;) – coson

4

Sí, es prácticamente lo mismo.

Se puede hacer referencia a este artículo en Coding Horror

+0

+1 para el enlace. Interesante discusión sobre este tema. – CAbbott

14

Si la variable i es una variable de instancia, lo hará se le asignará el valor 0 automáticamente. Si se trata de una variable local en un método, no está definido, por lo que deberá asignarle un valor antes de usarlo.

Por ejemplo:

class Program 
{ 
    static void Main(string[] args) 
    { 
     intTest it; 

     it = new intTest(); 

     Console.ReadLine(); 
    } 

    class intTest 
    { 
     int i; 

     public intTest() 
     { 
      int i2; 

      Console.WriteLine("i = " + i); 
      Console.WriteLine("i2 = " + i2); 
     } 
    } 
} 

Lo anterior no compilará porque i2 es sin asignar. Sin embargo, mediante la asignación de 0 a i2, es decir

int i2 = 0; 

y compilación, a continuación, ejecutar, mostrará que ambos están ahora asignados 0.

+0

int es una estructura, no una clase. las estructuras tienen un valor predeterminado mientras que las clases son nulas por defecto. –

+0

@Matthew Whited, no quería decir que fuera una clase. Él estaba diciendo en la clase "nivel", lo que realmente significa variable de instancia. Lo edité para aclaración. – mmcdole

0

Cada vez que se crea un tipo en C#, automáticamente se rellena con ceros acolchados. En el caso de una clase (tipo de referencia), esto equivale a un puntero nulo. Así que, técnicamente, cada vez que se trabaja con las clases, los siguientes son idénticos:

MyClass class; 
MyClass class2 = null; 

Con los tipos de valor (de cualquier estructura, incluyendo int/float/double/etc), el tipo se pasa con ceros, por lo los siguientes son equivalentes:

int i; 
int j = 0; 

Sin embargo, en un método, el compilador comprueba para ver si ha asignado un valor a sus tipos antes de usarlo. Si lo hace lo siguiente, el compilador se quejará:

int i; 
Console.WriteLine{"{0}",i); 

Técnicamente, lo anterior debe estar bien - pero ya que es una fuente común de error del programador, el compilador comprueba específicamente para las variables locales no asignados, y se queja. Sin embargo, esta es una queja en tiempo de compilación, y no un problema de CLR. Puedes hacer IL que haga lo anterior, y funciona bien.

0

Estos sólo son equivalentes para los campos (variables de clase). Los campos se asignan automáticamente a los valores predeterminados cuando la clase se inicializa. Dentro de un método o propiedad, la variable no asignada permanece sin asignar y causará un error de compilación si intenta acceder a su valor.

1

Con todo esto, vale la pena mencionar la palabra clave "predeterminada" en C#.

I.e. int i; es equivalente a int i = default(int); lo que equivale a int i = 0; y MyClass o = default(MyClass); es equivalente a MyClass o = null;

Esto es especialmente relevante cuando se utilizan métodos de LINQ como .SingleOrDefault() porque se puede utilizar siempre la siguiente para que su código sea más legible:

int someValue = collection.<various linq methods>.SingleOrDefault(); 
if (someValue == default(int)) 
{ 
    //Code for the default case 
} 

y

MyClass someValue = collection.<various linq methods>.SingleOrDefault(); 
if (someValue == default(MyClass)) 
{ 
    //Code for the default case 
} 
0

varias respuestas aquí son una especie de engañar, incluyendo XX Se hace referencia al artículo en el sitio web "Coding Horror".

El compilador optimizará su código para eliminar todas las inicializaciones "innecesarias" cuando se configure para optimizar el código generado. Tenga en cuenta que este es el comportamiento predeterminado al compilar en el modo "Versión".

Yo, por ejemplo, creo que siempre es muy útil inicializar todas sus variables. El rendimiento será mínimo en el modo de depuración y ninguno en el modo de lanzamiento, pero las ganancias de establecer explícitamente las variables serán tremendas para cualquiera que mantenga el código en el futuro, en el mejor estilo de "documentación del código con código". Recuerdo a este compañero de trabajo muy experimentado que pensó que el valor predeterminado de Int32 era Int32.MinValue en lugar de 0. Estos tipos de confusión siempre suceden a cosas implícitas en el código y, para mí, deberían evitarse en la mayoría de los casos.

Cuestiones relacionadas