2011-01-22 9 views

Respuesta

14

Tenga en cuenta que los campos se inicializan de manera implícita a null, así que esto sólo afecta a las variables. En pure C# usted no puede consultar el valor de un campo no inicializado (necesita "asignación definitiva"), por lo que no es cuestión.

Usted puede hacer esto mediante el abuso de IL aunque - al declarar un parámetro out, y el uso de DynamicMethod escribir un método que no asignarla (válido en IL, pero no en C#). Y luego verá que verá null s.

Esto a su vez se debe a una bandera IL (.locals init) que dice "borrar la pila para mí antes de entrar en este método" en la llamando código (C#). El compilador de C# siempre establece este indicador. Si vuelve a abusar de IL para escribir un método que no establece este indicador, probablemente pueda ver basura. Podría ser cualquier cosa. Pero en este punto, que se merece las excepciones se obtiene :)

He aquí un ejemplo de la primera (no el segundo, que es más complejo):

delegate void AbuseMe(out object foo); 
static void Main() { 
    DynamicMethod dyn = new DynamicMethod("Foo", 
     typeof(void), new[] { typeof(object).MakeByRefType() }); 
    dyn.GetILGenerator().Emit(OpCodes.Ret); 
    AbuseMe method = (AbuseMe) dyn.CreateDelegate(typeof(AbuseMe)); 
    object obj; // this **never** gets assigned, by **any** code 
    method(out obj); 
    Console.WriteLine(obj == null); 
} 

Para mayor claridad, el código DynamicMethod es simplemente escribiendo el equivalente a este código, no es legal en C#:

static void Foo(out object whatever) { } // note, whatever is not assigned 

esto funciona porque por lo que el CLR se refiereout no existe - sólo hay ref . Entonces, esto no es inválido. IL: solo el lenguaje (C#) le da significado al out y exige que se le asigne un valor.

El problema es que Main() todavía tiene la bandera .locals init; así que detrás de las escenas objestá borrado a null (bueno, todo el espacio de la pila simplemente se borra). Si compilé desde IL sin esa bandera (y tenía algún otro código en su lugar para ensuciar el espacio de la pila) pude ver basura. Puede ver más sobre .locals init en el blog Liran Chen's.

Pero para responder a la pregunta: ¿

  • de campos: campos de tipo de referencia sin inicializar son null - garantizado por la especificación
  • para las variables: no se puede pedir, pero como una implementación detalle (que no hay que dependía): sí, será null a pesar de que no se puede pedir; p
+2

Ok, eso es bastante extraño sh! T! :) – leppie

+0

@leppie Quiero agradar; p –

+0

Jeffrey Richter en su libro "CLR Via C#, 3rd edition" menciona que las variables siempre se inicializan por CLR a 'null'. También dice que en realidad no es necesario que el compilador de C# prohíba el uso de variables no inicializadas, pero el compilador todavía tiene esta restricción. –

3

"depende"

Para variables normales miembro cuando un valor no está especificado en la declaración entonces la variable asume el valor predeterminado adecuado (null para los tipos de referencia). Es decir, class A { string X; } es lo mismo que class A { string X = null; }.

Para variables locales es un error acceder a ellas antes de que se pueda demostrar que se ha asignado un valor. A pesar de que su tipo "predeterminado" es nulo (para tipos de referencia), ¡no están predeterminados por defecto! Es decir, string F() { string x; return x; } es un error en tiempo de compilación.

Recuerde: null es null :-)

Cuestiones relacionadas