Wyrażenia lambda pozwalają na uproszczenie zapisu do wymaganego minimum. Zobaczymy na przykładzie jak od zwykłej metody przejść do wyrażenia lambda.
class Program
{
static void Main(string[] args)
{
List<int> intList = new List<int>
{
1,2,3,4,5,6,7,8,9,10
};
List<int> matchedInts = intList.FindAll(new Predicate<int>(IsEven));
foreach (var item in matchedInts)
{
Console.WriteLine(item);
}
}
private static bool IsEven(int i)
{
return i % 2 == 0;
}
}
Pytanie tylko czy takie rozwiązanie jest nam na rękę? Metodę IsEven wykorzystamy tylko raz w naszym programie więc po co ją zapisywać globalnie? C# umożliwia skorzystanie z metod anonimowych tak więc powyższą funkcję możemy zapisać jako:
class Program
{
static void Main(string[] args)
{
List<int> intList = new List<int>
{
1,2,3,4,5,6,7,8,9,10
};
List<int> matchedInts = intList.FindAll(delegate(int i)
{
return i % 2 == 0;
});
foreach (var item in matchedInts)
{
Console.WriteLine(item);
}
}
}
Rozwiązanie całkiem niezłe, jednak można jeszcze lepiej za pomocą wyrażeń lambda:
class Program
{
static void Main(string[] args)
{
List<int> intList = new List<int>
{
1,2,3,4,5,6,7,8,9,10
};
List<int> matchedInts = intList.FindAll(i => { return i % 2 == 0; });
foreach (var item in matchedInts)
{
Console.WriteLine(item);
}
}
}
Całkiem nieźle. Dużo mniej kodu a taki sam efekt. Czas na składnię:
lista parametrów => instrukcje
i => {return i % 2 == 0;}
Teraz kilka faktów:
Jeżeli delegat nie przyjmuje parametrów nasze wyrażenie zapisujemy jako:
() => instrukcje
Jeżeli delegat przyjmuje więcej niż 1 parametr, delegatę zapisujemy jako:
(i, j, ...) => instrukcje
Jeżeli parametry nie można zidentyfikować po typie, możemy je przekazać jawnie:
(int i, string j) => instrukcje
C# dostarcza nam predefiniowane delegaty:
Func
Func<int, int, int> AddTwoIntegers = (a, b) => { return a + b; };
Console.WriteLine(AddTwoIntegers(5, 5));
Action<int> action = x => { x = x * 5; Console.WriteLine(x); };
action(10);
Predicate<int> predicate = x => { return x % 2 == 0; };
Console.WriteLine(predicate(21));
Zobaczmy jeszcze na jeden aspekt:
Podczas debugowania naszych metod możemy uświadczyć następującego widoku:
Metoda jest przekształcana do strumienia, można w tym przypadku wykorzystać klasę Expression i otrzymać bardziej czytelniejszy kod:
Jednym aspektem, który z pewnością nas zmartwi jest to, iż nie każdy Func może zostać przekształcony do drzewa decyzyjnego. Niektóre przykłady musimy sami przekształcać.
Delegat nie delegata.
OdpowiedzUsuńPoprawione. Pozdrawiam.
OdpowiedzUsuń