Wyrażenie Lambda
Degusto
Wstęp
Przed podejściem do wyrażeń lambda warto zapoznać się z Delegaty.
Definicja
Wyrażenia lambda to funkcje anonimowe, które zostały wprowadzone do C# w wersji 3.0. Nie należy jednak mylić ich z metodami anonimowymi z wersji 2.0.
Metody anonimowe: https://msdn.microsoft.com/pl-pl/library/0yw3tz5k.aspx
Składnia
Wyrażenie lambda ma następującą składnię:
(parametry) => {zwracana wartość}
(int a, int b) => {return a + b;}
Prosty przykład:
Func<int, int, int> foo = (int a, int b) => { return a + b; };
Console.WriteLine(foo(5, 4));
Jednak składnia wyrażenia nie zawsze musi tak wyglądać, mianowicie:
-
Typ parametru nie musi być podawany
-
Jeśli podawany jest jeden parametr to nawiasy () nie muszą występować
-
Jeśli jedyną instrukcją jest return to możemy pominąć nawiasy {}, słówko return oraz średnik
Dzięki temu możemy uzyskać jeszcze krótsze formy np.:
Func<int, int, int> foo = (a, b) => { return a + b; };
Func<int, int, int> foo = (int a, int b) => a + b;
Func<int, int, int> foo = (a, b) => a + b;
Func<int, int> foo = a => a * 5;
Co jeśli nie chcemy przesyłać parametrów, albo chcemy wykonać więcej niż jedną instrukcję? Żaden problem:
Func<int> foo = () =>
{
int a = 5;
return a;
};
Console.WriteLine(foo());
Zmienne zewnętrzne
W wyrażeniach lambda możliwe jest odnoszenie się do zmiennych, do których mamy dostęp w danym zakresie:
int x = 5;
Func<int> foo = () => x;
Console.WriteLine(foo());
Ponadto nawet jeśli zmodyfikujemy wartość x między linijką 2 i 4 to w wyrażeniu i tak będzie aktualna wartość:
int x = 5;
Func<int> foo = () => x;
x = 6;
Console.WriteLine(foo());
Możemy nie mieć nawet dostępu do zmiennej x w momencie wywołania foo np. wtedy gdy zwrócimy wyrażenie jako wynik metody, wtedy x będzie posiadało ostatnią aktualną wartość:
using System;
class Program
{
static void Main()
{
TestFoo.Foo();
Console.ReadKey();
}
}
class TestFoo
{
public static Func<int> Testuj()
{
int x = 5;
Func<int> foo = () => x;
x = 6;
return foo;
}
public static void Foo()
{
var foo = Testuj();
Console.WriteLine(foo());
}
}
Inny dosyć ciekawy przykład, który pozwala nam zobaczyć możliwości zewnętrznych zmiennych:
using System;
class Program
{
static void Main()
{
TestFoo.WiekszeNizN(100);
Console.ReadKey();
}
}
class TestFoo
{
public static Func<int, bool> TestujacaFunkcja(int n)
{
return x => x > n;
}
public static void WiekszeNizN(int x)
{
var funkcja = TestujacaFunkcja(50);
Console.WriteLine(funkcja(x));
}
}
Praktyczny przykład
Wyrażenia lambda wykorzystywane są między innymi w LINQ, poniżej przykład, który przeszukuje listę i zwraca nową listę tylko tych zmiennych, które spełniają warunek:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
var lista = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var nowaLista = lista.Where(zmienna => zmienna > 5).ToList<int>();
foreach (var liczba in nowaLista)
{
Console.WriteLine(liczba);
}
Console.ReadKey();
}
}
W powyższym kodzie, przekazujemy wyrażenie lambda do metody Where. Metoda Where dla każdego elementu w liście będzie wywoływała przesłane wyrażenie podając dany element jako parametr wejściowy, a na podstawie rezultatu(true/false) dodawała lub nie element do nowej kolekcji(zwracanej przez metodę Where).