Jaka jest różnica między tymi dwoma odmianami wyrażeń inicjujących kolekcję?

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

Używam C # przez jakiś czas, ale ostatnio zauważyłem, że zachowanie jednego z moich testów jednostkowych zmieniło się w zależności od używanej przeze mnie wersji inicjalizatora kolekcji:

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

Do tego momentu zakładałem, że druga forma była po prostu cukrem syntaktycznym i była semantycznie równoważna pierwszej formie. Jednak przełączanie się między tymi dwiema formami spowodowało, że mój niesprawny test jednostkowy przeszedł.

Poniższy przykładowy kod demonstruje to:

 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; }
} 

Kiedy to uruchomię, pierwsze zadanie działa dobrze, ale drugie powoduje NullReferenceException .

Mam przeczucie, że kompilator traktuje te dwa wyrażenia za kulisami:

 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); 

Czy to założenie jest dokładne?

1 Comments

1 Answers


Jon Skeet 07/31/2017.

Tak, twoje założenie jest dokładne. Jeśli inicjator obiektu po prostu ma:

{
    Property = { ... }
} 

zamiast

{
    Property = expression
} 

wtedy setter dla właściwości nie jest używany - używany jest getter , a następnie wywoływana jest metoda Add lub właściwości są ustawiane w zwracanej wartości. Więc:

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

jest równa:

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

Porównaj to z:

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

co jest równoznaczne z:

// 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
Czy nie powinien być ekwiwalentem nowej kolekcji, czy tylko ją dodaje?

Related questions

Hot questions

Language

Popular Tags