2011-04-18 17 views
5

Estaba leyendo This Article en el blog de Jag Reeghal y me pareció que lo que estaba sugiriendo realmente no era lo mismo que usar un inicializador de objetos. Entonces me di cuenta de que realmente no lo sabía con certeza.¿Se construye un objeto si se lanza un inicializador?

Cuando se construye un objeto, con inicializadores de objeto y uno de esos iniciadores lanza (tal vez una excepción de referencia nula) ... ¿se construye realmente el objeto? ¿Es básicamente como una excepción lanzada en el constructor? ¿O el objeto está completamente construido y luego inicializado?

Respuesta

3

Una declaración objeto initilizer como var x = new Foo { Property1 = 5}; será implementado como algo parecido a esto:

Foo temp = new Foo(); 
temp.Property1 = 5; 
x = temp; 

Como se puede ver, las propiedades en el initiallizer se establecen después de que el objeto se construye, sin embargo, la variable no se establece al objeto completamente inicializado hasta todas las propiedades están establecidas, por lo que si se lanza una excepción , el objeto construido se pierde incluso si se captura la excepción (la variable seguirá siendo null o cualquier valor que tuviera antes).

+0

Así, mientras diferente, los resultados son los mismos que si un thows constructor. Entonces, mi opinión de que la recomendación de Jag no es realmente la misma es correcta. –

+0

Los resultados son casi los mismos. Puede haber una diferencia en lo que queda en la memoria después de la excepción. Jag recomienda que ReSharper limite las sugerencias del inicializador a 10 propiedades; de lo contrario, puede ser muy difícil depurarlo cuando hay demasiada información en una sola línea de código. –

1

El objeto se construirá, pero la inicialización no se completará. La inicialización es solo un truco de compilación; mira la IL generada y verás que es la misma de cualquier manera. La publicación del blog se queja de que es más difícil decir en qué línea se produjo la excepción, pero personalmente nunca he tenido esa dificultad.

2

Primero se construye por completo, luego se inicializa. Sin embargo, nunca obtendrá una referencia a dicho objeto si se lanza una excepción, el compilador se asegura de que su referencia solo se refiera a un objeto correctamente inicializado. Utiliza un temporal para garantizar esto.

Así, por ejemplo, este código:

var obj = new Model { 
    FirstName = reader[0].ToString(), 
    LastName = reader[1].ToString(), 
    Age = Convert.ToInt32(reader[2].ToString()) 
}; 

se reescribe por el compilador para:

var temp = new Model(); 
temp.FirstName = reader[0].ToString(); 
temp.LastName = reader[1].ToString(); 
temp.Age = Convert.ToInt32(reader[2].ToString()) 
var obj = temp; 
0

Todos ustedes deben ser conscientes de la IL compilado no es siempre la misma !!

La diferencia está en las configuraciones de compilación Debug/Release.

Tenga una mirada en el reflector si no me creen .....

Cuestiones relacionadas