Wyrażenia C # Lambda: dlaczego powinienem ich używać?

Szybko przeczytałem dokumentację Microsoft Lambda Expression .

Ten przykład pomógł mi lepiej zrozumieć:

delegate int del(int i);
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
Nie rozumiem, dlaczego to taka innowacja. To tylko Metoda, która umiera, gdy kończy się "zmienna metody", prawda? Dlaczego powinienem używać tego zamiast prawdziwej metody?
Author: skia.heliou, 2008-10-03

14 answers

Wyrażenia Lambda są prostszą składnią dla anonimowych delegatów i mogą być używane wszędzie tam, gdzie może być użyty anonimowy delegat. Jednak nie jest odwrotnie; wyrażenia lambda mogą być konwertowane do drzew wyrażeń, co pozwala na wiele magii, takich jak LINQ do SQL.

Poniżej znajduje się przykład LINQ to Objects wyrażenia używając anonimowych delegatów, a następnie wyrażeń lambda, aby pokazać, o ile są one łatwiejsze dla oka:

// anonymous delegate
var evens = Enumerable
                .Range(1, 100)
                .Where(delegate(int x) { return (x % 2) == 0; })
                .ToList();

// lambda expression
var evens = Enumerable
                .Range(1, 100)
                .Where(x => (x % 2) == 0)
                .ToList();

Lambda wyrażenia i Anonimowi delegaci mają przewagę nad pisaniem osobnej funkcji: implementują zamknięcia , które pozwalają przekazać lokalny stan funkcji bez dodawania parametrów do funkcji lub tworzenia obiektów jednorazowego użytku.

Drzewa wyrażeń są bardzo potężną nową cechą C# 3.0, która pozwala API spojrzeć na strukturę wyrażenia zamiast tylko uzyskać odniesienie do metody, która może być wykonywana. API po prostu musi aby dodać parametr delegata do parametru Expression<T>, kompilator wygeneruje drzewo wyrażeń z lambda zamiast anonimowego delegata:

void Example(Predicate<int> aDelegate);

Nazywany jak:

Example(x => x > 5);

Staje się:

void Example(Expression<Predicate<int>> expressionTree);

Ten ostatni otrzyma reprezentację abstrakcyjnego drzewa składniowego opisującego wyrażenie x > 5. LINQ to SQL polega na tym zachowaniu, aby móc włączyć wyrażenia C# do wyrażeń SQL wymaganych do filtrowania / zamawiania / etc. na serwerze bok.

 265
Author: Neil Williams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-14 07:48:05

Anonimowe funkcje i wyrażenia są przydatne dla jednorazowych metod, które nie korzystają z dodatkowej pracy wymaganej do utworzenia pełnej metody.

Rozważ ten przykład:

 string person = people.Find(person => person.Contains("Joe"));

Kontra

 public string FindPerson(string nameContains, List<string> persons)
 {
     foreach (string person in persons)
         if (person.Contains(nameContains))
             return person;
     return null;
 }

Są funkcjonalnie równoważne.

 132
Author: Joseph Daigle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 03:59:01

Uznałem je za przydatne w sytuacji, gdy chciałem zadeklarować obsługę jakiegoś zdarzenia kontrolki, używając innej kontrolki. Aby zrobić to normalnie, trzeba będzie przechowywać odniesienia controls ' w polach klasy, tak, że można ich używać w innej metodzie niż zostały utworzone.

private ComboBox combo;
private Label label;

public CreateControls()
{
    combo = new ComboBox();
    label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += new EventHandler(combo_SelectedIndexChanged);
}

void combo_SelectedIndexChanged(object sender, EventArgs e)
{
    label.Text = combo.SelectedValue;
}

Dzięki wyrażeniom lambda można go używać w następujący sposób:

public CreateControls()
{
    ComboBox combo = new ComboBox();
    Label label = new Label();
    //some initializing code
    combo.SelectedIndexChanged += (s, e) => {label.Text = combo.SelectedValue;};
}
Dużo łatwiej.
 82
Author: agnieszka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-19 17:57:13

Lambda wyczyścił składnię anonimowego delegata C # 2.0...na przykład

Strings.Find(s => s == "hello");

Zrobiono w C# 2.0 TAK:

Strings.Find(delegate(String s) { return s == "hello"; });

Funkcjonalnie, robią dokładnie to samo, to tylko o wiele bardziej zwięzła składnia.

 34
Author: FlySwat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 15:52:43

Jest to tylko jeden sposób użycia wyrażenia lambda. Możesz użyć wyrażenia lambda w dowolnym miejscu , w którym możesz użyć delegata. To pozwala robić takie rzeczy:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

strings.Find(s => s == "hello");

Ten kod przeszukaÄ ‡ listÄ ™ wpisăłw pasujÄ ... cych do sĹ ' owa "hello". Innym sposobem, aby to zrobić, jest przekazanie delegata do metody Find, jak to:

List<string> strings = new List<string>();
strings.Add("Good");
strings.Add("Morning")
strings.Add("Starshine");
strings.Add("The");
strings.Add("Earth");
strings.Add("says");
strings.Add("hello");

private static bool FindHello(String s)
{
    return s == "hello";
}

strings.Find(FindHello);

EDIT :

W C# 2.0 można to zrobić używając składni anonymous delegate:
  strings.Find(delegate(String s) { return s == "hello"; });

Lambda ' s znacznie poprawił składnię.

 28
Author: Scott Dorman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 15:25:42

Microsoft dał nam czystszy, wygodniejszy sposób tworzenia anonimowych delegatów zwanych wyrażeniami Lambda. Jednak nie zwraca się zbyt wiele uwagi na wyrażenia część tego stwierdzenia. Microsoft wydał całą przestrzeń nazw, System.Linq.Expressions , która zawiera klasy do tworzenia drzew wyrażeń opartych na wyrażeniach lambda. Drzewa wyrażeń składają się z obiektów, które reprezentują logikę. Na przykład X = y + z jest wyrażeniem, które może być częścią drzewa wyrażeń w .Net. rozważ następujący (prosty) przykład:

using System;
using System.Linq;
using System.Linq.Expressions;


namespace ExpressionTreeThingy
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<Func<int, int>> expr = (x) => x + 1; //this is not a delegate, but an object
            var del = expr.Compile(); //compiles the object to a CLR delegate, at runtime
            Console.WriteLine(del(5)); //we are just invoking a delegate at this point
            Console.ReadKey();
        }
    }
}

Ten przykład jest trywialny. I jestem pewien, że myślisz: "jest to bezużyteczne, ponieważ mogłem bezpośrednio utworzyć delegata zamiast tworzyć wyrażenie i kompilować je w czasie wykonywania". I miałbyś rację. Ale to stanowi fundament dla drzew ekspresji. Istnieje wiele wyrażeń dostępnych w przestrzeniach nazw wyrażeń i możesz tworzyć własne. Myślę, że to widzisz. może to być przydatne, gdy nie wiesz dokładnie, jaki algorytm powinien być w czasie projektowania lub kompilacji. Widziałem gdzieś przykład użycia tego do napisania kalkulatora naukowego. Można go również używać do systemów bayesowskich lub do programowania genetycznego (AI). Kilka razy w swojej karierze musiałem napisać funkcjonalność podobną do Excela, która pozwalała użytkownikom na wprowadzanie prostych wyrażeń (dodawanie, podwarianty, itp.), aby operować na dostępnych danych. W pre-.Net 3.5 musiałem uciekać się do jakiś język skryptowy zewnętrzny do C#, lub musiał użyć funkcji emitowania kodu w reflection do tworzenia kodu. Net w locie. Teraz użyłbym drzew wyrazu.

 21
Author: Jason Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-09 05:42:10

Zapisuje konieczność posiadania metod, które są używane tylko raz w określonym miejscu przed zdefiniowaniem z dala od miejsca, w którym są używane. Dobre zastosowania są jako komparatory dla ogólnych algorytmów, takich jak sortowanie, gdzie można następnie zdefiniować niestandardową funkcję sortowania, gdzie wywołujesz sortowanie, a nie dalej zmuszając cię do szukania gdzie indziej, aby zobaczyć, na czym sortujesz.

I to nie jest tak naprawdę innowacja. LISP posiada funkcje lambda od około 30 lat lub więcej.

 11
Author: workmad3,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 15:14:24

Wyrażenie lambda jest jak anonimowa metoda napisana w miejsce instancji delegata.

delegate int MyDelagate (int i);
MyDelagate delSquareFunction = x => x * x;

Rozważmy wyrażenie lambda x => x * x;

Wartość parametru wejściowego to x (po lewej stronie=>)

Logika funkcji to x * x (po prawej stronie=>)

Kod wyrażenia lambda może być blokiem instrukcji zamiast wyrażeniem.

x => {return x * x;};

Przykład

Uwaga: Func jest predefiniowanym rodzajem delegat.

    Console.WriteLine(MyMethod(x => "Hi " + x));

    public static string MyMethod(Func<string, string> strategy)
    {
        return strategy("Lijo").ToString();
    }

Referencje

  1. W Jaki Sposób delegat i interfejs mogą być używane zamiennie?
 6
Author: Lijo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:42

Można również znaleźć użycie wyrażeń lambda w pisaniu ogólnych kodów do działania na swoich metodach.

Na przykład: funkcja Ogólna do obliczania czasu zajętego przez wywołanie metody. (tj. Action tutaj)

public static long Measure(Action action)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    action();
    sw.Stop();
    return sw.ElapsedMilliseconds;
}

I możesz wywołać powyższą metodę używając wyrażenia lambda w następujący sposób:

var timeTaken = Measure(() => yourMethod(param));

Wyrażenie pozwala na uzyskanie wartości zwracanej z metody i out param, jak również

var timeTaken = Measure(() => returnValue = yourMethod(param, out outParam));
 5
Author: Gunasekaran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-07 10:25:56

Często używasz funkcjonalności tylko w jednym miejscu, więc tworzenie metody po prostu zaśmieca klasę.

 4
Author: Darren Kopp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 15:14:21

Wyrażenie Lambda jest zwięzłym sposobem reprezentowania anonimowej metody. Zarówno metody anonimowe, jak i wyrażenia Lambda pozwalają zdefiniować implementację metody inline, jednak metoda anonimowa jawnie wymaga zdefiniowania typów parametrów i typu zwracanego dla metody. Wyrażenie Lambda używa funkcji wnioskowania typu W C# 3.0, która pozwala kompilatorowi wnioskować typ zmiennej na podstawie kontekstu. Jest to bardzo wygodne, ponieważ oszczędza nam to wiele pisanie!

 4
Author: Vijesh VP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 15:19:16

Jest to sposób na małą operację i umieszczenie jej bardzo blisko miejsca, w którym jest używana(w przeciwieństwie do deklarowania zmiennej blisko jej punktu użycia). To ma sprawić, że Twój kod będzie bardziej czytelny. Anonimizując wyrażenie, znacznie utrudniasz komuś złamanie kodu klienta, jeśli ta funkcja jest używana gdzie indziej i modyfikowana w celu jej "ulepszenia".

Podobnie, dlaczego musisz używać foreach? Możesz zrobić wszystko w foreach za pomocą pętli plain for lub po prostu za pomocą IEnumerable bezpośrednio. Odpowiedź: nie potrzebujesz , ale to sprawia, że Twój kod jest bardziej czytelny.

 3
Author: plinth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-03 15:19:00

Innowacja polega na bezpieczeństwie typu i przejrzystości. Chociaż nie deklarujesz typów wyrażeń lambda, są one wywnioskowane i mogą być używane przez wyszukiwanie kodu, analizę statyczną, narzędzia refaktoryzacji i odbicie środowiska uruchomieniowego.

Na przykład, zanim użyłeś SQL i mogłeś uzyskać atak SQL injection, ponieważ haker przekazał ciąg znaków, w którym normalnie Oczekiwano liczby. Teraz użyjesz LINQ lambda expression, która jest przed tym chroniona.

Budowanie API LINQ w przypadku czystych delegatów nie jest to możliwe, ponieważ wymaga połączenia drzew wyrażeń przed ich oceną.

W 2016 roku większość popularnych języków ma wsparcie wyrażenia lambda , A C# był jednym z pionierów tej ewolucji wśród głównych języków imperatywnych.

 0
Author: battlmonstr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-21 14:56:37

To chyba najlepsze wyjaśnienie dlaczego używać wyrażeń lambda - > https://youtu.be/j9nj5dTo54Q

Podsumowując, ma to poprawić czytelność kodu, zmniejszyć ryzyko błędów poprzez ponowne użycie zamiast powielania kodu i wykorzystać optymalizację za kulisami.

 0
Author: coffeeeee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-19 22:40:36