piątek, 7 grudnia 2012

Ewolucja lambda expression

Na początku był delegat.


Delegat jest odpowiednikiem wskaźnika do funkcji w C/C++. Jest silnie typowany, co oznacza, że delegat może wskazywać tylko na określony typ metody. Dajmy na to, że potrzebujemy sprawdzić czy pewna wartość jest większa czy mniejsza od zadanego progu. Stwórzmy delegat, który będzie miał 2 argumenty (wartość zmiennej oraz wartość progu) i będzie zwracał bool.
delegate bool ComparisonDelegate
(int value, int threshold);


public static bool IsGreaterThan
(int value, int threshold)
{
    return value > threshold;
}


public static bool IsLessThanOrEqualTo
(int value, int threshold)
{
    return value <= threshold;
}

Zastosowanie takiego delegata wygląda następująco:

ComparisonDelegate greaterThan = 
new ComparisonDelegate(IsGreaterThan);

ComparisonDelegate lessThanOrEqualTo =
new ComparisonDelegate( IsLessThanOrEqualTo);

bool is1GreaterThan3 = 
greaterThan(1, 3);

bool is5LessThanOrEqualTo4 = 
lessThanOrEqualTo(5, 4);

Takie rozwiązanie składała się z wielu linijek kodu oraz z paru oddzielnych części (deklaracja delegata, napisanie oddzielnych metod, inicjacja instancji delegatu, wywołanie delegata).Początki są ciężkie :)
Pierwszym uproszczeniem jest zastosowanie nazwanych metod. Już nie jest potrzebne wywołanie konstruktora z parametrem do metody, tylko wystarczyło podać nazwę metody.
ComparisonDelegate greaterThan = IsGreaterThan;
W .NET 2.0 przyszedł na świat koncept zwany metodami anonimowymi.
delegate bool ComparisonDelegate(int value, int threshold);


ComparisonDelegate greaterThan = delegate
(int value, int threshold)
{
return value > threshold;
};

bool is1GreaterThan3 = greaterThan(1, 3);

Dzięki anonimowym metodom można wprowadzić logikę biznesową do 'ciała'. Już nie musimy deklarować dodatkowych metod. Skoro teraz za każdym razem kiedy tworzymy instancje używamy słowa 'delegate' to można to zamienić na znak '=>'.
ComparisonDelegate greaterThan = 
delegate(int value, int threshold)
{
return value > threshold;
};
ComparisonDelegate greaterThan = 
(int value, int threshold)=>
{
return value > threshold;
};
Od momentu zamiany słowa delegate na znak '=>' mamy do czynienia z lambda expression. Lambda expression są rozwinięciem anonimowych metod. W tym kodzie znak '=>' oznacza, że pobiera 2 argumenty typu int, a zwraca bool. Jeszcze możemy usunąć klamry:
ComparisonDelegate greaterThan = 
(int value, int threshold)=> 
value > threshold;
I skoro wiemy, że ComparisonDelegate przyjmuje dwa argumentami typu int, to możemy tą zduplikowaną informację też usunąć.
ComparisonDelegate greaterThan = 
(value, threshold)=> 
value > threshold;
Po takich operacjach, składnia jest krótsza i czytelniejsza. Całość wygląda następująco:
delegate bool ComparisonDelegate(int value, int threshold);

ComparisonDelegate greaterThan =
(value, threshold)=> 
value > threshold;

bool is1GreaterThan3 = greaterThan(1, 3);
Wraz z .NET 3.5 (c#3.0) możemy użyć generycznego delegata o nazwie Funk. Dzięki temu nie będziemy musieli deklarować dodatkowego elementu. Deklaracja wygląda następująco:
delegate bool ComparisonDelegate(int value, int threshold);

delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
Zamieniamy ComparisonDelegate na Func:
Func<int, int, bool> greaterThan = 
(value, threshold)=> 
value > threshold;
Jak widać przejście z delegatów do lambda expressions jest całkiem ... szybkie:)

Brak komentarzy:

Prześlij komentarz