to specjalny przypadek inicjator zbiórki.
W języku C# inicjatory nawiasów macierzy zostały uogólnione do pracy z dowolnym konstruktorem klasy kolekcji.
Każda klasa obsługuje te, jeśli implementuje System.Collections.IEnumerable
i ma jedną lub więcej metod Add()
. Eric Lippert has a good post about this type of "pattern matching" in C#: To, co robi tutaj kompilator, to coś, co nazywają "duck typing", a nie konwencjonalnie silnie typowane OOP, w którym możliwości klasy są rozpoznawane na podstawie dziedziczenia i implementacji interfejsu. C# robi to w kilku miejscach. W tym artykule nie znalazłem zbyt wielu rzeczy.
public class Foo : List<String>
{
public void Add(int n)
{
base.Add(n.ToString());
}
public void Add(DateTime dt, double x)
{
base.Add($"{dt.ToShortDateString()} {x}");
}
}
A potem to kompiluje:
var f = new Foo { 0, 1, 2, "Zanzibar", { DateTime.Now, 3.7 } };
To cukier syntaktyczny na to:
var f = new Foo();
f.Add(0);
f.Add(1);
f.Add(2)
f.Add("Zanzibar");
f.Add(DateTime.Now, 3.7);
Można grać całkiem dziwne gry z nich. Nie wiem, czy to dobry pomysł, aby wyjść na całość (w rzeczywistości I do wiem - to nie jest), ale możesz. Napisałem klasę analizatora wiersza poleceń, w której można zdefiniować opcje za pomocą inicjatora kolekcji. Ma kilkanaście przeciążeń Add
z różnymi listami parametrów, wiele z nich jest generycznych. Wszystko, co kompilator może wywnioskować, jest grą fair.
Ponownie, możesz zmniejszyć tę liczbę do momentu nadużywania funkcji.
Co widzisz jest rozszerzeniem, gdzie pozwala zrobić inicjator zbiórki na niezbywalnej członka, że sama klasa już utworzonego samej składni inicjatora:
public class Bar
{
public Foo Foo { get; } = new Foo();
}
A teraz .. .
var b = new Bar { Foo = { 0, "Beringia" } };
{ 0, "Beringia" }
jest inicjator zbierania na przykład Foo
że Bar
utworzonej na siebie; to cukier syntaktyczny na to: chęć
var b = new Bar();
b.Foo.Add(0);
b.Foo.Add("Beringia");
kompilatora, aby rozwiązać przeciążeniem Foo.Add()
w używaniu inicjatora syntaktyczne cukru ma sens, jeśli spojrzeć na to w ten sposób. Myślę, że wspaniale jest móc to zrobić, ale nie jestem w 100% zadowolony z wybranej przeze mnie składni. Jeśli odnalazłeś operatora przypisania jako czerwonego śledzia, inni też.
Ale nie jestem Arbiter składni, a to chyba najlepiej dla wszystkich zainteresowanych.
Wreszcie, również współpracuje z inicjatorów obiektu:
public class Baz
{
public String Name { get; set; }
}
public class Bar
{
public Foo Foo { get; } = new Foo { 1000 };
public Baz Baz { get; } = new Baz { Name = "Initial name" };
}
Więc ...
var b = new Bar { Foo = { 0, "Beringia" }, Baz = { Name = "Arbitrary" } };
które faktycznie zamienia się ...
var b = new Bar();
b.Foo.Add(0);
b.Foo.Add("Beringia");
b.Baz.Name = "Arbitrary";
Nie można zainicjować Bar.Baz
ponieważ nie ma on ustawiacza, ale możemy zainicjować jego właściwości tak, jak możemy to zainicjować ems w Foo
. I to prawda, nawet jeśli zostały już zainicjowane przez inicjator innego obiektu dołączony do rzeczywistego konstruktora.
Inicjatory kolekcji, jak można się spodziewać, są kumulatywne: Bar.Foo
będą miały trzy pozycje: .
Kiedy myślisz o nawiasach klamrowych jako skrótach do kolumn instrukcji przypisania lub Add()
wywołań przeładowania, wszystkie są skupione.
Ale zgadzam się, że znak równości jest drażniący w przypadkach, w których l-wartość nie jest faktycznie przypisana.
Bonus
Oto kolejny wzorzec dopasowania funkcja dowiedziałem się o from that Eric Lippert article:
public static class HoldMyBeerAndWatchThis
{
public static IEnumerable<int> Select(Func<String, String> f)
{
yield return f("foo").Length;
}
}
Dlatego ...
var x = from s in HoldMyBeerAndWatchThis select s;
Wszystko, czego potrzebujesz do select
do pracy jest to, że rzeczą, którą” ponowne wybieranie z musi mieć metodę o nazwie Select
, która zwraca coś , który znachoruje jakIEnumerable
zgodnie z opisem w komentarzach @ EricLipperta na temat foreach
w (dzięki Eric!) I przyjmuje parametr Func<T,T>
.
Po prostu odkryłem to również tego samego dnia, nie byłem też w stanie dokładnie określić, jak to działa. – DLeh
Zgodnie z [dokumentami MSDN na temat inicjalizatorów] (https://msdn.microsoft.com/en-us/library/bb384062.aspx) wydaje się, że kompilacja wielokrotnie wywołuje 'Dodaj' podczas używania tego inicjalizatora. Zauważ, że nie możesz użyć tej składni bezpośrednio w deklaracji zmiennej. na przykład 'IList children = {" childfoo "," childbar "}' nie skompiluje –
@ stephen.vakil: Czasami prawie można. 'string [] children = {" childfoo "," childbar "};' – recursive