Pregunta

¿Hay algún modo obtener una referencia a la instancia que estoy creando de acuerdo al objeto initialiser

var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }

"este" debe apuntar a la nueva instancia TestClass estoy creando. Pero es evidente que se refiere la instancia de la clase en la que reside este código.

No estoy preguntando si esto es una buena manera de hacer esto. Soy consciente de que puedo hacer esto de esta manera:

var x = new TestClass {Id= x};
x.SomeProperty = SomeMethod(this);

Tengo un escenario complicado, en el que una referencia a la nueva instancia en el objeto initialiser haría la vida más fácil.

Es posible esto de alguna manera?

¿Fue útil?

Solución

No hay manera de evitarlo, el C # especificación dice explícitamente que " no es posible que un objeto o una colección inicializador para referirse a la instancia del objeto se inicializa ".

En cuanto a por qué es imposible, sospecho que simplemente no hay buena manera de ponerla en práctica. Queremos algún equivalente de azúcar sintáctica a

var temp = new TestClass();
temp.Id = 1;
temp.SomeProperty = SomeMethod(temp);
x = temp;

Sólo necesitamos una palabra clave para referirse a temp dentro del inicializador, pero ninguno es de fácil acceso. No podemos utilizar this porque ya significa algo fuera del inicializador. SomeProperty = this.SomeMethod(this) debe ser equivalente a temp.SomeProperty = this.SomeMethod(temp) o temp.SomeProperty = temp.SomeMethod(temp)? La segunda es consistente, pero entonces ¿qué ocurre si necesitamos la primera?

podría tratar de usar x, aunque sólo podemos escoger un nombre si el nuevo objeto se le asigna inmediatamente a una variable. Sin embargo, ahora no podemos hacer referencia al valor antiguo de x dentro del inicializador, haciendo el equivalente de temp.SomeProperty = SomeMethod(x).

podría volver a utilizar la palabra clave value de los emisores de propiedad. Esto suena bien, ya value ya se encuentra en el parámetro que falta, si se tiene en cuenta una propiedad de captador ser azúcar sintáctico para un método set_SomeProperty(value). Usarlo para referirse también a la variable que falta en el inicializador de objeto parece prometedor. Sin embargo, podríamos estar creando este objeto dentro de un regulador de la propiedad, en la que ya se está utilizando value caso, y tenemos que ser capaces de hacer temp.SomeProperty = SomeMethod(value).

Parece que vamos a tener que crear una nueva palabra clave para este fin, tal vez newthis. Sin embargo, este es un cambio importante a la lengua, ya que cualquier código que tiene una variable llamada newthis no funciona más. Microsoft necesita generalmente una muy buena razón para introducir cambios romper, por lo que es mejor prohibir el acceso al objeto que se está inicializado.

Otros consejos

No, no se puede utilizar el objeto de inicialización para asignar el objeto que se está creando en otro lugar - que derrotas el punto central de la inicializador de objeto. La variable x no quede asignado hasta después de que se complete la inicialización de objetos. Tendrá que asignar el objeto, a continuación, utilizarlo en otro comunicado.

var x = new TestClass {
    Id = 1
};
x.SomeProperty = SomeMethod(x);
var x = new TestClass
           {
                 Id = 1,
                 SomeProperty = SomeMethod(this)
           }

Antes de la parte derecha de esta inicialización es evaluado y ejecutado, aún no se ha puesto a disposición la referencia al nuevo objeto al código. Esto se hace por razones de seguridad, de lo contrario podría crear algún punto muerto o bucle sin fin, con su código.

La exposición o el uso de un objeto que no se ha construido totalmente por lo general es una muy mala idea. Considere lo siguiente:

class Connection
{
    internal string connectionString;
    public Connection(ConnectionPool pool, string connectionString) {
        this.pool = pool;
        //this.connectionString = connectionString; // I moved it because I could.
        this.pool.Register(this);
        this.connectionString = connectionString;
        this.Init();        
    }

    private void Init() { //blah }
}

class ConnectionPool
{
     public void Register(Connection c)
     {
         if ( this.connStrings.Contains( c.connectionString ) ) // BOOM
     }
}

Este es un ejemplo extremadamente artificial. Las cosas pueden ponerse mucho peor que esto. El siguiente era bastante un enlace interesante respecto a este tema: parcialmente construido objetos

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top