remarks cref c# collection-initializer

c# - cref - ¿Cuál es la diferencia entre estas dos variaciones de expresiones de inicializador de colección?



remarks c# (1)

He estado usando C # por un tiempo, pero recientemente noté que el comportamiento de una de mis pruebas de unidad cambió según la variación de la expresión de inicializador de colección que usé:

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

Hasta este punto asumí que la segunda forma era solo azúcar sintáctica y era semánticamente equivalente a la primera forma. Sin embargo, cambiar entre estas dos formas resultó en que mi prueba de unidad fallada se pasara

El código de ejemplo a continuación demuestra esto:

void Main() { var foo1 = new Foo { Items = new List<int> { 1, 2, 3} }; var foo2 = new Foo { Items = { 1, 2, 3 } }; foo1.Dump(); foo2.Dump(); } class Foo { public List<int> Items { get; set; } }

Cuando ejecuto esto, la primera asignación funciona bien, pero la segunda resulta en una NullReferenceException .

Mi intuición es que detrás de escena el compilador está tratando estas dos expresiones de la siguiente manera:

var foo1 = new Foo(); foo1.Items = new List<int> { 1, 2, 3 }; var foo2 = new Foo(); foo2.Items.Add(1); foo2.Items.Add(2); foo2.Items.Add(3);

¿Es ese supuesto exacto?


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

{ Property = { ... } }

más bien que

{ Property = expression }

luego no se usa el establecedor de la propiedad; se usa el captador , y luego se llama al método Add o se establecen las propiedades 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;

Compara eso con:

var foo = new Foo { Collection = new List<int> { 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<int> { 1 }; foo.Property = new Bar { Value = 1 };