¿Cuál es la diferencia entre estas dos variaciones de expresiones de inicialización de colección?

Tagc 09/16/2017. 1 answers, 803 views
c# collection-initializer

He estado usando C # por un tiempo, pero recientemente noté que el comportamiento de una de las pruebas de mi unidad cambió dependiendo de la variación de la expresión del inicializador de la colección que utilicé:

  • var object = new Class { SomeCollection = new List { 1, 2, 3 } };
  • var object = new Class { SomeCollection = { 1, 2, 3 } };

Hasta este punto asumí que la segunda forma era simplemente azúcar sintáctica y era semánticamente equivalente a la primera forma. Sin embargo, el cambio entre estas dos formas dio como resultado el fallecimiento de mi unidad de prueba.

El siguiente código de ejemplo demuestra esto:

 void Main()
{
    var foo1 = new Foo { Items = new List { 1, 2, 3} };
    var foo2 = new Foo { Items = { 1, 2, 3 } };

    foo1.Dump();
    foo2.Dump();
}

class Foo
{
    public List Items { get; set; }
} 

Cuando ejecuto esto, la primera asignación funciona bien, pero el segundo da como resultado una NullReferenceException .

Mi instinto es que detrás de las escenas el compilador está tratando estas dos expresiones como esta:

 var foo1 = new Foo();
foo1.Items = new List { 1, 2, 3 }; 

var foo2 = new Foo();
foo2.Items.Add(1);
foo2.Items.Add(2);
foo2.Items.Add(3); 

Es esa suposición exacta?

1 Comments
Leon Barkan 07/31/2017

1 Answers


Jon Skeet 07/31/2017.

Sí, su suposición es precisa. Si un inicializador de objetos solo tiene:

{
    Property = { ... }
} 

más bien que

{
    Property = expression
} 

entonces no se usa el setter para la propiedad - se usa el getter y luego se llama al método Add o las propiedades se establecen dentro del valor devuelto. Asi que:

var foo = new Foo
{
    Collection = { 1 }
    Property =
    {
        Value = 1
    }
}; 

es equivalente a:

// Only the *getters* for Collection and Property are called
var foo = new Foo();
foo.Collection.Add(1);
foo.Property.Value = 1; 

Compare eso con:

var foo = new Foo
{
    Collection = new List { 1 },
    Property = new Bar { Value = 1 }
}; 

que es equivalente a:

// The setters for Collection and Property are called
var foo = new Foo();
foo.Collection = new List { 1 };
foo.Property = new Bar { Value = 1 }; 
1 comments
1 Ash Burlaczenko 07/31/2017
¿No debería el equivalente a también la nueva colección o simplemente agrega?

Related questions

Hot questions

Language

Popular Tags