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).

0 komentarzy