fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
4 minut

Lambda expressions – explained


26.03.2008

Lambda expressions – brzmi groźnie. To właśnie tym elementem języka C# 3.0 straszono programistów (a raczej programiści straszyli się nawzajem) jeszcze dobre kilkanaście miesięcy przed premierą .NET 3.5. A bo to “funkcyjne”, a bo to “nowe”, “nieznane” i trudne do pojęcia. Jak za chwilę zobaczymy – nic bardziej mylnego. Jeżeli kiedykolwiek korzystałeś z delegatów, to umiesz korzystać także z metod anonimowych. Jeżeli umiesz korzystać z metod anonimowych, to… to są właśnie wyrażenia lambda, tylko trochę bardziej topornie zapisane!

W tym poście nie będę zajmował się samym mechanizmem delegatów, to materiał na osobny wpis (który być może kiedyś powstanie).

Na początek zaprezentuję przykład, który pozwoli nam rozłożyć zagadnienie na czynniki pierwsze:

 1:   delegate TResult MyFunc<TResult, T1, T2>(T1 arg1, T2 arg2);
2: int Process(int a, int b, MyFunc<int, int, int> operation)
3: {
4: return operation(a, b);
5: }

W .NET 3.5 nie musimy tworzyć własnego delegata – możemy posłużyć się klasą Func:

 int Process(int a, int b, Func<int, int, int> operation);

Zadanie metody Process jest proste: przyjąć dwie liczby oraz operację, która ma być na nich wykonana, a następnie zwrócić wynik owej operacji. Załóżmy, że zależy nam na dodaniu tych liczb. Na dzień dzisiejszy mamy aż 4 (cztery!) sposoby na uzyskanie takiego efektu. Po kolei:

W .NET 1.x mogliśmy użyć standardowej, najbardziej “rozwlekłej” notacji składającej się z dwóch kroków: deklaracji metody i przekazania jej nazwy. Dwa absolutnie równoważne sposoby to:

 1:   private int Adder(int arg1, int arg2)
2: {
3: return arg1 + arg2;
4: }
5:
6: int longest = Process(1, 2, new MyFunc<int, int, int>(Adder));
7: int shorter = Process(2, 3, Adder);

Twórcy .NET 2.0 uraczyli nas możliwością bezpośredniego przekazania kodu, czyli stworzenie metody anonimowej:

int anonymousMethod = Process(3, 4, delegate(int a1, int a2) { return a1 + a2; });

W C# 3.0 możemy z kolei zrobić coś takiego:

int lambdaExpression = Process(4, 5, (a1, a2) => a1 + a2);

Zaglądając Reflectorem zobaczymy:

 1:   [CompilerGenerated]
2: private static MyFunc<int, int, int> CS$<>9__CachedAnonymousMethodDelegate2; // metoda anonimowa
3: [CompilerGenerated]
4: private static MyFunc<int, int, int> CS$<>9__CachedAnonymousMethodDelegate3; // wyrażenie lambda
5:
6: private void Foo()
7: {
8: int longest = Process(1, 2, new MyFunc<int, int, int>(Program.Adder));
9: int shorter = Process(2, 3, new MyFunc<int, int, int>(Program.Adder)); // identyczne jak powyżej
10: if (CS$<>9__CachedAnonymousMethodDelegate2 == null)
11: {
12: CS$<>9__CachedAnonymousMethodDelegate2 = delegate (int a1, int a2) {
13: return a1 + a2;
14: };
15: }
16: int anonymousMethod = Process(3, 4, CS$<>9__CachedAnonymousMethodDelegate2);
17: if (CS$<>9__CachedAnonymousMethodDelegate3 == null)
18: {
19: CS$<>9__CachedAnonymousMethodDelegate3 = delegate (int a1, int a2) {
20: return a1 + a2;
21: };
22: }
23: int lambdaExpression = Process(4, 5, CS$<>9__CachedAnonymousMethodDelegate3);
24: }

Wniosek jest oczywisty: wyrażenia lambda to po prostu nowy sposób utworzenia anonimowej metody – i NIC poza tym. Kod wygenerowany dla lambda niczym się nie różni od kodu wygenerowanego dla anonymous method. O co więc tyle szumu? Tylko i wyłącznie o zapis, który jest teraz bardziej “funkcyjny” (lub “elegancki”, a już na pewno – krótszy). Nie podajemy typów parametrów, nie używamy “return”… wszystko dzieje się “samo”.

Nie przegap kolejnych postów!

Dołącz do ponad 9000 programistów w devstyle newsletter!

Zapisując się na newsletter zgadzasz się na przetwarzanie Twoich danych osobowych w celu wysyłania na wskazany przez Ciebie adres e-mail informacji handlowych o nowościach, promocjach, produktach i usługach związanych z serwisem devstyle.pl. Będzie to marketing bezpośredni, do realizacji którego wykorzystam Twoje telekomunikacyjne urządzenia końcowe. Administratorem Twoich danych osobowych będzie Maciej Aniserowicz prowadzący działalność gospodarczą w Białymstoku (15-215) przy ul. Konopnickiej 14/8, NIP 5422824401. Przysługuje Tobie prawo do cofnięcia zgody, żądania wglądu do Twoich danych, wniesienia sprzeciwu co do ich przetwarzania, sprostowania, usunięcia i ograniczenia przetwarzania. Więcej informacji o tym jak przetwarzam Twoje dane znajdziesz na devstyle.pl/RODO. Powered by ConvertKit
Notify of
Jacek Ciereszko

Przeczytany, zrozumiany, dzięki :)

p.s. dodaj "kick it" albo coś w tym rodzaju, to będziemy klikać i wykopywać :]

Procent

Spx, more is coming.

Co do kicków, diggów itd to bez szczególnej przyczyny wyłączyłem je. Nie wiem właściwie dlaczego więc może faktycznie nadejdzie moment gdy "enabled" zostanie na nich wciśnięte, dzięki za pomysł:).

mgrzeg

Krotko i na temat. 5 punktow! :)

huhu78
huhu78

Próbuję poznać i zrozumieć LINQ-SQL od kilku dni. Zanim przeczytałem Twój artykuł, patrzyłem na => => => jak na pismo supełkowe. Teraz zatrybiłem. Dzięki.

Kurs Gita

Zaawansowany frontend

Szkolenie z Testów

Szkolenie z baz danych

Facebook

Książka

Zobacz również