2011-05-25 8 views
48

Duplicar posible:
Cannot use ‘this’ in member initializer?¿Por qué no puedes usar 'esto' en los inicializadores de miembros?

Cualquier idea por qué me da un error si trato de hacer algo como esto:

public class Bar 
{ 
    public Bar(Foo foo) 
    { 
    } 
} 

public class Foo 
{ 
    private Bar _bar = new Bar(this); 
} 

me sale un error que dice:

"No se puede usar 'esto' en el inicializador de miembro"

pero las siguientes obras:

public class Foo 
{ 
    private Bar _bar; 

    public Foo() 
    { 
     _bar = new Bar(this); 
    } 
} 

Alguien sabe la razón detrás de esto? Según entendí, estos compilarían para la misma IL, de modo que tengo curiosidad por saber por qué uno está permitido y el otro no.

Gracias, Alex

+0

No estoy seguro de por qué esta pregunta se cierra como un duplicado, ya que la respuesta a la otra pregunta es por qué no se informó porque se respondió un error con "esto es un error en el compilador" sin realidad explicando por qué no fue permitido. – Powerlord

Respuesta

52

I sospechoso es para evitar que la utilización del objeto antes al menos ha ejecutar el constructor de la clase base, asegurando que todos los miembros de la clase de base se inicializan de manera apropiada. (Inicializadores de variables se ejecutan antes la clase constructor base, mientras que el cuerpo del constructor se ejecuta después de eso.)

comprobará si la especificación anotada tiene nada que decir acerca de esto cuando estoy al lado cerca de ella ..

EDITAR: La especificación anotada C# 4 no tiene ninguna explicación. Solo (en 10.5.5.2):

Un inicializador variable para un campo de instancia no puede hacer referencia a la instancia que se está creando.

+0

Interesante, gracias. Nunca se dio cuenta de que los inicializadores variables se ejecutaban antes de la clase base ctor ... – AlexC

+19

Usted es, por supuesto, correcto. Deberíamos agregar que para la próxima edición de la especificación anotada, esa es buena. –

+1

Ahí va VS sugerencia de convertir mis campos de respaldo a 'Lazy' –

13

Los inicializadores de campo se ejecutan antes de los constructores de la clase base por lo que this aún no existe. Existe solo una vez que el constructor base ha terminado de ejecutarse.

17.10.2 Instance variable initializers:

Cuando un constructor de instancias no tiene inicializador constructor, o tiene un inicializador constructor de la base con forma (...), que constructor implícitamente realiza las inicializaciones especifican por los inicializadores de variable de los campos de instancia declarados en su clase. Esto corresponde a una secuencia de asignaciones que se ejecutan inmediatamente después de la entrada en el constructor y antes de la invocación implícita del constructor de clase de base directa . Los inicializadores variables se ejecutan en el orden textual en el que aparecen en la declaración de clase.

+1

Bueno, existe, simplemente no está completamente inicializado aún. –

0

Creo que esto se debe a que los campos inicializar antes de la clase inicializa por lo que cuando se ejecuta el código siguiente:

private Bar _bar = new Bar(this); 

"esto" no tiene ningún valor real que se hace referencia.

Mientras que poner en el constructor significa que hay una instancia de referenciable "Foo" por "este"

0

En C#, ninguna lógica está destinada a ser métodos fuera y propiedades cuerpos.

Los inicializadores de campo son una excepción, pero con algunas limitaciones.

Sería equivocado conseguir una referencia de objeto actual con este palabra clave porque una declaración de campo de clase no es lógica, sino el diseño de clases, mientras que este es parte de la semántica en tiempo de ejecución.

Por cierto, parece que es una decisión de diseño de C#, porque, de hecho, un inicializador de campo se ejecuta durante la construcción de clases, por lo que "se declara la instancia actual de la clase" debe estar disponible a través de este . Pero de nuevo, ¿cuál sería este fuera de un alcance de cuerpo de método o propiedad?

Como Jon Skeet y otros señalaron, este no está disponible porque los inicializadores de campo se ejecutan después de la ejecución del constructor base.

+0

Fuera de un método o cuerpo de propiedad, todavía sería el objeto en cuyo contexto se estaba ejecutando el código. Sería perfecto * sentido * permitir esto para los inicializadores de miembros - simplemente tendría problemas si intentara usar un estado que aún no había sido inicializado por la clase base. –

+0

Absolutamente de acuerdo y gracias por el comentario. Es por eso que señalo el hecho de que esta es una decisión de diseño de C#, pero formulo la pregunta porque me resulta confuso tener ** esta ** palabra clave en este ámbito (puede ser fácilmente un conjunto de errores). –

+0

ías: Pero tenga en cuenta que con el * pequeño * cambie a C# para que actúe más como Java (donde el constructor de la superclase se ejecuta antes de los inicializadores de la variable) la causa de los errores desaparecería. Creo * fundamentalmente * tiene sentido, es solo que hay algunas advertencias. –

0

Los inicializadores de miembros se ejecutan antes del constructor de clase. Considere que puede tener muchos inicializadores de miembro en una sola clase.

Si usa 'this' en el constructor -> se inicializaron todos los miembros con inicializadores. Entonces todo está bien.

Si usa 'esto' en el inicializador de miembros: otros miembros (con inicializadores adjuntos) pueden no haberse inicializado todavía -> 'esto' aún no está listo. Es por eso que usar 'esto' no está permitido aquí no está permitido.

Cuestiones relacionadas