Inicjalizacja obiektów z kolekcjami.

O dwóch sposobach inicjalizacji właściwości obiektu pisałem już tutaj. Dziś chciałbym pokazać jak zainicjalizować kolekcję używając “nowego” mechanizmu wprowadzonego w C# 3.0. Z poprzedniego post’a wiadomo, że właściwości można ustawiać tak:

internal class Person
{
    public Person()
    {
    }
   public List<string> Collection { get; set; }
   public string Name { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var person = new Person {Name = "Piotr", Collection = new List<string>()};
    }
}

Istnieje jednak dodatkowy operator, który chyba nie jest tak bardzo oczywisty. Jeśli chcielibyśmy dodać elementy do kolekcji możemy:

internal class Person
{
    public Person()
    {
        Collection=new List<string>();
    }
   public List<string> Collection { get; set; }
   public string Name { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var person = new Person {Name = "Piotr", Collection = {"A", "B", "C"}};
        foreach (var item in person.Collection)
            Console.WriteLine(item);
    }
}

CLR jest na tyle inteligentny, że jeśli kolekcja implementuje interfejs ICollection (posiada metodę Add) wtedy konstrukcja w postaci {lista_elementów} dodaje elementy a nie nadpisuje. Aby potwierdzić działanie dodajmy część elementów już w konstruktorze:

internal class Person
{
    public Person()
    {
        Collection=new List<string>();
        Collection.Add("F");
    }
   public List<string> Collection { get; set; }
   public string Name { get; set; }
}

Następnie uruchamiając powyższą inicjalizację na ekranie wyświetli się F,A,B,C a nie A,B,C  – elementy zostały dodane a nie nadpisane. Konstrukcja jest podobna ale różni się jednak trochę od inicjalizatora tablic, który wygląda następująco:

internal class Person
{
    public Person()
    {
    }
   public string[] Items { get; set; }
   public string Name { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var person = new Person {Name = "Piotr", Items = new[] {"A", "B", "C"}};
        foreach (var item in person.Items)
            Console.WriteLine(item);
    }
}

Powyższa konstrukcja to zwykłe utworzenie tablicy zatem elementy zostaną nadpisane (jeśli jakieś istniały przedtem). Oczywiście inicjalizacja kolekcji nie jest ograniczona tylko do powyższych przykładów. Każda lista (i inne klasy implementujące ICollection) można inicjalizować następująco:

internal class Program
{
    private static void Main(string[] args)
    {
        List<string> items = new List<string>() {"A", "B", "C"};
    }
}

Analogicznie wygląda sytuacja ze słownikami:

Dictionary<string, string> items = new Dictionary<string, string>()
                                               {{"klucz", "wartość"}, {"klucz2", "wartosc2"}};

5 thoughts on “Inicjalizacja obiektów z kolekcjami.”

  1. Intersujące, a mógłbyś tak jak w poprzednim poście pokazać zdekompilowany kod, jasne jest że każdy może to zrobić samemu reflectorem, ale wydaje mi się, że to fajnie uzupełnia post 😉

  2. var items = new List() {“A”, “B”, “C”};
    – to jest fajny syntactic sugar. Metoda Add z ICollection, czyli dokładnie jak piszesz.

    Jednak:
    var person = new Person {Name = “Piotr”, Collection = {“A”, “B”, “C”}};
    – kompletne zero intuicyjności. Nigdy bym nie pomyślał, że te elemnty mogą chcieć się dodać do już instniejących.

    @Piotr zgodzisz się?

  3. @Krzysztof Morcinek:
    Ja tez myslalem, ze to inicjalizuje liste a nie dodaje elementy do juz istniejacej. Nie jest to zbyt intuicyjne ale czy masz lepszy pomysl jak by mogli to zaimplementowac?

  4. @Krzysztof Morcinek:
    A jeszcze jest gorsza sytuacja w której Collection jest NULLEM – wtedy zakończy to się wyjątkiem. Jest to kompletnie nieintuicyjne ponieważ takie coś np:
    string[] a = {“a”, “b”};
    inicjalizuje tablice. W przypadku listy musi byc ona juz zaincjalizowana.

Leave a Reply

Your email address will not be published.