2010-10-15 9 views
6

Dla Hardcore C# koderów tutaj, może to wydawać się zupełnie głupie pytanie - ale ja właśnie natknąłem się na fragmencie kodu próbki w forum AWS SDK i został całkowicie sideswiped przez niego:C# syntax sugar - nowy sposób ustawiania atrybutów obiektów?

RunInstancesRequest runInstance = new RunInstancesRequest() 
    .WithMinCount(1) 
    .WithMaxCount(1) 
    .WithImageId(GetXMLElement("ami")) 
    .WithInstanceType("t1.micro"); 

Jest bardzo przypomina starą składnię VB6 With ... End With, którą od dawna ubolewałem nad brakiem w C# - skompilowałem ją w moim projekcie VS2008 i działa to przyjemnie, oszczędzając liczne oddzielne linie odnoszące się do tych atrybutów indywidualnie.

Jestem pewien, że czytałem artykuły w przeszłości wyjaśniają dlaczego VB6 stylu With -blok nie było w języku C#, więc moje pytanie brzmi: czy tej składni zawsze istniała w języku, czy jest to ostatnia zmiana .NET, która ją włączyła? Czy możemy pokryć wszystkie wystąpienia obiektów, a następnie zmiany atrybutów w tym samym cukrze?

+2

No pewnie, można wdrożyć wszystko te metody, jeśli chcesz. Ale dlaczego nie wystarczy użyć składni inicjalizatora obiektu? –

+1

Doskonałe odpowiedzi tutaj, ale mogę tylko zaakceptować jedną - więc na razie to właśnie odnosi się do * Fluent Interfacing *, ponieważ przykład w artykule jasno wyjaśnia, co się dzieje. Czuję się nieco zawstydzony, że nie wykonałem intuicyjnego połączenia, zauważając, że linia jako całość ma postać "A.B.C.D;", ale nigdy wcześniej nie widziałem tej techniki. Kolejny sznur do łuku! :) –

Odpowiedz

16

realizowane one wszystkie te metody, z których każdy będzie również zwrócenie obiektu RunInstancesRequest (aka, this). Nazywa się to Fluent Interface

+0

Ładny link. Podoba mi się ten przykład: http://en.wikipedia.org/wiki/Fluent_interface#C.23 –

4

To nie jest cukier syntaktyczny. Te metody ustawiają właściwość i zwracają obiekt this.

0

Składnia ta istniała zawsze

25

Czy to nie jest lepsze?

RunInstancesRequest runInstance = new RunInstancesRequest 
{ 
    MinCount = 1, 
    MaxCount = 1, 
    ImageId = GetXMLEleemnt("ami"), 
    InstanceType = "t1.micro" 
}; 
+1

+1 Uwielbiam uczyć się nowych rzeczy. – Brad

+0

Zgadzam się, dla ustawienia właściwości/konstruktorów jest to lepsza składnia. Ale w scenariuszach, w których pracujesz z istniejącym przedmiotem i często zmieniasz kilka właściwości lub wywołujesz kilka metod w łańcuchu, płynne interfejsy świecą. Jest to jeden z wielu powodów, z którymi jQuery jest tak przyjemnie pracować. – CaffGeek

+1

I nie można go używać na niezmiennym obiekcie. Osobiście uważam, że ta składnia powinna być używana tylko wtedy, gdy oryginalny obiekt nie jest zmodyfikowany (jak w Linq). – CodesInChaos

1

Powodem tego składnia działa dla RunInstancesRequest jest to, że każda metoda wymaga, że ​​robisz powrót oryginalnej instancji. Ta sama koncepcja może być zastosowana do StringBuilder z tego samego powodu, ale nie wszystkie klasy mają metody zaimplementowane w ten sposób.

3

Myślę, że ta technika różni się od składni With ... w VB. Myślę, że jest to przykład łączenia. Każda metoda zwraca instancję samego siebie, aby można było łańcuchować wywołania metod.

Zobacz Method-Chaining in C#

+0

+1 Wyższe odpowiedzi w rankingu nie wspominają o łańcuchowaniu. –

1

wolałbym o konstruktor, który ma wszystkie te wartości nieruchomości jako argumenty i ustawia je w klasie.

+0

+1. Nie podoba mi się to, co pozwala, by częściowo zbudowane klasy żyły. Po prostu muszę znieść to dla LINQ2SQL lub innych ORMów jako artefaktu impedancji OO-ORM, ale nie ma usprawiedliwienia przez większość czasu. Nie oznacza to, że nie można go używać obok właściwych konstruktorów i niezmienników klasy, ale widzę, jak to by zachęcało do zerwania z tym. –

4
RunInstancesRequest runInstance = new RunInstancesRequest() 
.WithMinCount(1) 
.WithMaxCount(1) 
.WithImageId(GetXMLElement("ami")) 
.WithInstanceType("t1.micro"); 

==

RunInstancesRequest runInstance = new RunInstancesRequest().WithMinCount(1).WithMaxCount(1).WithImageId(GetXMLElement("ami")).WithInstanceType("t1.micro"); 

Nie wiem, czy to jest uważany za cukier syntaktyczny, lub po prostu czysta formatowanie.

+0

+1: biała czcionka wokół '.' jest (i zawsze była) całkowicie ignorowana przez kompilator. –

1

To zawsze istniał w C# i rzeczywiście w dowolnym języku oo C-Style (eh, najbardziej popularny język C-style z wyjątkiem C sobie!)

To niesprawiedliwe porównanie go do składni VB6 With...End With, jak to dużo jaśniejsze, co się dzieje w tej sprawie (o jedynej dobrej rzeczy, którą mam do powiedzenia na temat VB6's With...End With, przynajmniej nie jest tak źle jak Javascript, ponieważ wymaga wcześniejszych kropek).

Tak jak powiedzieli ludzie, połączenie "płynnego interfejsu" i faktu, że operator . dopuszcza odstępy przed i po nim, dzięki czemu możemy umieścić każdy element na linii nowej.

StringBuilder jest najczęściej postrzegane przypadek w języku C#, jak w:

new StringBuilder("This") 
    .Append(' ') 
    .Append("will") 
    .Append(' ') 
    .Append("work") 
    .Append('.'); 

Podobną, ale nie do końca to samo, wzór jest gdzie łańcuch metod niezmiennej obiektu, który powraca inny przedmiot tego samego typu co w:

DateTime yearAndADay = DateTime.UtcNow.AddYears(1).AddDays(1); 

kolejny wraca zmodyfikowany IEnumerable<T> i IQueryable<T> obiekty z LINQ pokrewnych metod.

Te jednak różnią się zwracaniem różnych obiektów, a nie modyfikowaniem zmiennego obiektu i zwracaniem tego samego obiektu.

Jedną z głównych przyczyn częstszego występowania w C++ i Javu niż w C# jest to, że C# ma właściwości. To sprawia, że ​​najbardziej idiomatycznym sposobem przypisania różnych właściwości jest wywołanie powiązanego narzędzia ustawiającego, które jest składniowo takie samo jak ustawienie pola. Blokuje to jednak wiele z najbardziej powszechnych zastosowań płynnego idiomu interfejsu.

Osobiście, ponieważ biegły idiom interfejs nie jest gwarantowana (nie ma nic do powiedzenia MyClass.setProp(32) powinien powrócić this czy rzeczywiście, że nie powinien wrócić 32 który będzie również przydatny w niektórych przypadkach), a ponieważ nie jest tak idiomatyczne w języku C#, wolę unikać jej oprócz z StringBuilder, który jest takim przykładem dobrze wiedzą, że prawie nie istnieje jako odrębny StringBuilder idiomu w C#

Powiązane problemy