Udostępnij za pośrednictwem


Wyrażenia lambda (Podręcznik programowania C#)

Wyrażenie lambda jest funkcja anonimowa, który służy do tworzenia delegatów lub typy drzewa wyrażenie.Za pomocą wyrażenia lambda, można napisać funkcje lokalne, które mogą być przekazywane jako argumenty lub zwracane jako wartość wywołania funkcji.Wyrażenia lambda są szczególnie przydatne w przypadku wyrażeń zapytanie LINQ.

Aby utworzyć wyrażenie lambda, należy określić parametry wejściowe (jeśli są) po lewej stronie operatora lambda = >, i umieścić wyrażenie lub instrukcja blok po drugiej stronie.Na przykład, wyrażenie lambda x => x * x określa parametr o nazwie x i zwraca wartość x kwadratu.To wyrażenie można przypisać do typem obiektu delegowanego, jak pokazano w następującym przykładzie:

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

Aby utworzyć typ drzewa wyrażenia:

using System.Linq.Expressions;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<del> myET = x => x * x;
        }
    }
}

=> Operator ma ten sam priorytet, jako przydział (=) i są zespolone w prawo.

Lambdas są używane w oparte na metodzie LINQ kwerendy jako argumenty do standardowej kwerendy operator metod, takich jak Where.

Kiedy użyć składni oparte na metodzie do wywołania Where metoda w Enumerable klasy (tak jak w LINQ do obiektów i LINQ to XML) parametr jest typem obiektu delegowanego System.Func<T, TResult>.Wyrażenie lambda jest Najwygodniejszym sposobem tworzenia to pełnomocnik.Po wywołaniu tej samej metody, na przykład, System.Linq.Queryable klasy (tak jak w LINQ to SQL), a następnie typ parametru jest System.Linq.Expressions.Expression<Func> gdzie Func jest wszelkie Func delegatów do szesnastu parametrów wejściowych.Ponownie Wyrażenie lambda jest tylko bardzo zwięzły sposób do konstruowania tego wyrażenia drzewo.Zezwalaj na lambdas Where wywołania wyglądają podobnie, choć w rzeczywistości jest inny typ obiektu utworzonego z lambda.

W poprzednim przykładzie, obwieszczenie podpis pełnomocnik ma jedną niejawnie wpisane dane wejściowe parametr typu inti zwraca int.Wyrażenie lambda, można przekonwertować delegat tego typu, ponieważ ma jeden parametr wejściowy (x) i wartości zwracanej, że kompilator można niejawnie przekonwertować typu int.(Wnioskowanie jest omówione bardziej szczegółowo w poniższych sekcjach). Delegat jest wywoływana przy użyciu parametru wejściowego 5, zwraca w wyniku 25.

Lambdas nie są dozwolone po lewej stronie jest lub jako operatora.

Wszystkie ograniczenia dotyczące metody anonimowe stosuje się również do wyrażenia lambda.Aby uzyskać więcej informacji, zobacz Anonimowe metody (Podręcznik programowania C#).

Wyrażenie Lambdas

Wyrażenie lambda z wyrażenie po prawej stronie jest nazywany Wyrażenie lambda.Lambdas wyrażenie są szeroko stosowane do budowy Wyrażenie drzew (C# i Visual Basic).Wyrażenie lambda zwraca wynik wyrażenia i ma następującą postać podstawowe:

(input parameters) => expression

Nawiasy są opcjonalne, tylko jeśli lambda ma jeden parametr wejściowy; w przeciwnym razie są one wymagane.Dwa lub więcej parametrów wejściowych są oddzielone przecinkami, ujęta w nawiasy:

(x, y) => x == y

Czasami jest trudne lub niemożliwe dla kompilatora rozpoznać typy wejściowych.W takim przypadku można określić typy jawnie, jak pokazano w poniższym przykładzie:

(int x, string s) => s.Length > x

Określić zero parametrów wejściowych z pustych nawiasów:

() => SomeMethod()

Uwaga w poprzednim przykładzie, że organ lambda wyrażenie może składać się z wywołania metody.Jednakże w przypadku tworzenia drzewa wyrażenie, które będzie używane w innej domenie, takich jak SQL Server, nie należy używać wywołania metody w wyrażeniach lambda.Metody będzie nie mają znaczenia poza kontekstem .NET common language runtime.

Instrukcja Lambdas

Lambda instrukcja podobny do wyrażenia lambda, chyba że liczba zapytań: jest ujęty w nawiasy klamrowe:

(input parameters) => {statement;}

Ciała lambda instrukcja może składać się z dowolnej liczby instrukcji; Jednak w praktyce nie są zazwyczaj nie więcej niż dwa lub trzy.

delegate void TestDelegate(string s);
…
TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };
myDel("Hello");

Lambdas instrukcja, podobnie jak metody anonimowe, nie można utworzyć wyrażenie drzew.

Asynchroniczne Lambdas

Można łatwo utworzyć wyrażenia lambda i instrukcji, które zawierają przetwarzania asynchronicznego za pomocą async i await słowa kluczowe.Na przykład w poniższym przykładzie Windows Forms zawiera program obsługi zdarzeń, który wywołuje i czeka na metodę komunikacji asynchronicznej, ExampleMethodAsync.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private async void button1_Click(object sender, EventArgs e)
    {
        // ExampleMethodAsync returns a Task.
        await ExampleMethodAsync();
        textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
    }

    async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

Za pomocą transmisji asynchronicznej lambda, można dodać tego samego programu obsługi zdarzeń.Aby dodać ten program obsługi, dodać async modyfikator przed lambda listy parametrów, jak pokazano w następującym przykładzie.

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += async (sender, e) =>
        {
            // ExampleMethodAsync returns a Task.
            await ExampleMethodAsync();
            textBox1.Text += "\r\nControl returned to Click event handler.\r\n";
        };
    }

    async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

Aby uzyskać więcej informacji dotyczących sposobu tworzenia i używania metod asynchronicznych, zobacz Asynchroniczne programowania przy użyciu asynchronicznej i poczekać (C# i Visual Basic).

Lambdas z standardowe operatory zapytań

Wielu operatorów standardowej kwerendy ma parametr wejściowy, którego typ jest jednym z Func<T, TResult> rodziny rodzajowy delegatów.Func<T, TResult> Delegatów używać parametrów typu, aby określić liczbę i typ parametry wejściowe i zwraca typ delegata.FuncPełnomocnicy są bardzo przydatne do enkapsulacji wyrażeń zdefiniowanych przez użytkownika, które są stosowane do każdego elementu w zestawie danych źródłowych.Na przykład rozważmy następujący typ delegata:

public delegate TResult Func<TArg0, TResult>(TArg0 arg0)

Pełnomocnik może być utworzone jako Func<int,bool> myFunc gdzie int jest parametrem wejściowym i bool jest zwracana wartość.Zwracana wartość jest zawsze określony w ostatnim parametrze typu.**Func<int, string, bool>**Definiuje pełnomocnik z dwóch parametrów wejściowych, int i stringi zwraca typ bool.Następujące Func pełnomocnika, jest wywoływana, zwróci wartość true lub false, aby wskazać, czy parametr wejściowy jest równa 5:

Func<int, bool> myFunc = x => x == 5;
bool result = myFunc(4); // returns false of course

Można też podać wyrażenie lambda, gdy typ argumentu jest Expression<Func>, na przykład w przypadku operatorów standardowej kwerendy, które są zdefiniowane w System.Linq.Queryable.Po określeniu Expression<Func> argument, lambda zostanie skompilowany do drzewa wyrażenie.

Operator standardowej kwerendy, Count metoda, jest następujący:

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);

Kompilator można wywnioskować z typem parametru wejściowego, lub można również określić w sposób jawny.To wyrażenie lambda w szczególności liczy się tych liczb całkowitych (n) które podzielona przez dwa mieć resztę 1.

Poniższa metoda będzie produkcji zawierający wszystkie elementy w sekwencji numbers tablicy, które są do lewej strony, 9, ponieważ jest to pierwszy numer w sekwencji, która nie spełnia warunku:

var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);

Ten przykład pokazuje, jak określić wiele parametrów wejściowych, umieszczając je w nawiasach.Metoda zwraca wszystkie elementy w tablicy liczb, aż do wielu napotkanych, których wartość jest mniejsza niż położenie.Nie należy mylić operatora lambda (=>) z operatorem większe lub równe (>=).

var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

Wnioskowanie w Lambdas

Podczas pisania lambdas, często nie trzeba określić typ parametrów wejściowych, ponieważ kompilator można rozpoznać typu na podstawie treści lambda, podstawowy typ delegata i inne czynniki, jak opisano w specyfikacji języka C#.Większość operatorów standardowej kwerendy pierwsze wejście jest typu elementy w sekwencji źródłowej.Tak, jeśli wykonywana jest kwerenda IEnumerable<Customer>, a następnie być wywnioskowane zmienną wejściową Customer obiektu, co oznacza, masz dostęp do metod i właściwości:

customers.Where(c => c.City == "London");

Ogólne zasady dotyczące lambdas są następujące:

  • Lambda musi zawierać taką samą liczbę parametrów, jak typ delegata.

  • Każdy parametr wejściowy w lambda musi być jawnie konwertowany na jego odpowiedniego parametru delegata.

  • Wartość zwracana lambda (jeśli są) musi być jawnie konwertowany na typ zwracany przez delegata.

Należy zauważyć, że wyrażenia lambda same w sobie nie ma typu bo wspólny system typu ma wewnętrzne koncepcji "Wyrażenie lambda." Jednak czasami jest wygodne nieformalnie mówić "typu" Wyrażenie lambda.W tych przypadkach typu odnosi się do typu pełnomocnik lub Expression typu do którego wyrażenie lambda jest konwertowany.

Zakres zmiennej w wyrażenia Lambda

Lambdas może odnosić się do zewnętrzne zmiennych , które są w zakres otaczający metoda lub typu, w którym zdefiniowano lambda.Zmiennych, które są przechwytywane w ten sposób są przechowywane do użytku w wyrażenie lambda, nawet jeśli zmienne przeciwnym wypadku przejdź poza zakresem i być RuntimeCallableWrapper.Zmienna zewnętrzne należy przypisać zdecydowanie przed mogą być spożywane w wyrażenie lambda.Poniższy przykład ilustruje następujące zasady:

delegate bool D();
delegate bool D2(int i);

class Test
{
    D del;
    D2 del2;
    public void TestMethod(int input)
    {
        int j = 0;
        // Initialize the delegates with lambda expressions.
        // Note access to 2 outer variables.
        // del will be invoked within this method.
        del = () => { j = 10;  return j > input; };

        // del2 will be invoked after TestMethod goes out of scope.
        del2 = (x) => {return x == j; };
      
        // Demonstrate value of j:
        // Output: j = 0 
        // The delegate has not been invoked yet.
        Console.WriteLine("j = {0}", j);        // Invoke the delegate.
        bool boolResult = del();

        // Output: j = 10 b = True
        Console.WriteLine("j = {0}. b = {1}", j, boolResult);
    }

    static void Main()
    {
        Test test = new Test();
        test.TestMethod(5);

        // Prove that del2 still has a copy of
        // local variable j from TestMethod.
        bool result = test.del2(10);

        // Output: True
        Console.WriteLine(result);
           
        Console.ReadKey();
    }
}

Następujące zasady stosuje się do zakresu zmiennych w wyrażeniach lambda:

  • Zmienna, która są przechwytywane nie będą śmieci zbierane do pełnomocnika, który odwołuje się do niej wykracza poza zakres.

  • Zmienne wprowadzone w ramach wyrażenia lambda nie są widoczne w zewnętrzną metodę.

  • Wyrażenie lambda bezpośrednio nie może przechwytywać ref lub out parametr z otaczającym metody.

  • Instrukcja return Wyrażenie lambda nie powoduje otaczający metoda zwraca.

  • Nie może zawierać wyrażenie lambda goto instrukcji, break instrukcji, lub continue instrukcji, którego celem jest poza ciałem lub w treści zawarte funkcja anonimowa.

Specyfikacja języka C#

Aby uzyskać więcej informacji, zobacz Specyfikacja języka C#. Specyfikacja języka to najlepsze źródło informacji dotyczących składni i zastosowania języka C#.

Rekomendowane rozdziału książki

Delegates, Events, and Lambda ExpressionswC# 3.0 Cookbook, Third Edition: More than 250 solutions for C# 3.0 programmers

Zobacz też

Informacje

Anonimowe metody (Podręcznik programowania C#)

(C# odniesienia)

Koncepcje

Podręcznik programowania C#

Wyrażenie drzew (C# i Visual Basic)

Inne zasoby

LINQ (zintegrowane języka kwerend)

Wyrażenia lambda cykliczne