Lambda výrazy (Příručka programování C#)
Lambda výraz je anonymní funkce, můžete vytvořit delegáty nebo typy strom výrazů.Místní funkce, které mohou být předány jako argumenty nebo vráceno jako hodnota volání funkce můžete napsat pomocí lambda výrazy.Lambda výrazy jsou užitečné zejména pro psaní výrazy LINQ dotazů.
Lambda výraz vytvořit, můžete určit vstupní parametry (pokud existuje) na levé straně operátor lambda = >, a umístit blok výrazu nebo příkazu na druhé straně.Například lambda výraz x => x * x určuje parametr s názvem x a vrátí hodnotu x čtverců.Tento výraz můžete přiřadit typ delegáta, jak ukazuje následující příklad:
delegate int del(int i);
static void Main(string[] args)
{
del myDelegate = x => x * x;
int j = myDelegate(5); //j = 25
}
Vytvoření typu strom výrazu:
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Expression<del> myET = x => x * x;
}
}
}
=> Operátor má stejnou prioritu jako přiřazení (=) a je zprava asociativní.
Lambda výrazy používají metodu podle LINQ dotazy jako argumenty metody standardních dotazovacích operátorů, jako Where.
Při použití metody založené na syntaxi volání Where metoda Enumerable třídy (jako v LINQ objekty a Technologie LINQ to XML) parametr je typ delegáta System.Func<T, TResult>.Lambda výraz je nejpohodlnější způsob vytvoření tohoto delegáta.Při volání stejné metody, například System.Linq.Queryable třídy (jako v Technologie LINQ to SQL) je typ parametru System.Linq.Expressions.Expression<Func> kde je Func delegátů Func až šestnáct vstupních parametrů.Lambda výraz je opět pouze velmi stručný způsobem vytvořit výraz tree.Povolit lambda výrazy Where podobným, ačkoli ve skutečnosti je jiný typ objektu vytvořené z lambda volání.
V předchozím příkladu oznámení delegáta má jeden implicitně zadané vstupní parametr typu inta vrátí int.Lambda výraz může být převedena na delegáta typu, protože má jeden vstupní parametr (x) a hodnotu kompilátor implicitně převést zadejte int.(Odvození typu proměnné je popsána podrobněji níže.) Když je delegát vyvolán pomocí vstupní parametr 5, vrátí výsledek 25.
Lambda výrazy, které nejsou povoleny na levé straně je nebo jako operátor.
Všechna omezení, které se vztahují k anonymní metody platí také pro lambda výrazy.Další informace naleznete v tématu Anonymní metody (Příručka programování C#).
Lambda výrazy
Lambda výraz s výraz na pravé straně je volána lambda výraz.Lambda výrazy jsou používány v konstrukci Výraz stromů (C# a Visual Basic).Lambda výrazů vrátí výsledek výrazu a základní formu:
(input parameters) => expression
Závorky jsou nepovinné, pouze pokud lambda má jeden vstupní parametr jinak jsou vyžadovány.Dva nebo více vstupních parametrů jsou odděleny čárkami, které jsou uvedeny v závorkách:
(x, y) => x == y
Někdy je obtížné či nemožné kompilátor pro vstupní typy odvodit.V tomto případě můžete určit typy explicitně znázorněno v následujícím příkladu:
(int x, string s) => s.Length > x
Určit nulové vstupní parametry s prázdnými závorkami:
() => SomeMethod()
Poznámka: v předchozím příkladu, že subjekt lambda výrazů se může skládat z volání metody.Však pokud vytváříte stromy výrazů, které budou spotřebovány v jiné doméně, například SQL Server, neměli byste používat volání metody v lambda výrazy.Metody bude mít žádný význam mimo kontext .NET CLR.
Lambda
S výjimkou, že je příkazů uzavřeny ve složených závorkách se podobá příkazu lambda lambda výrazů:
(input parameters) => {statement;}
Subjekt lambda prohlášení může obsahovat libovolný počet příkazů; v praxi existují však obvykle ne více než dvě nebo tři.
delegate void TestDelegate(string s);
…
TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };
myDel("Hello");
Lambda jako anonymní metody nelze použít k vytvoření stromy výrazů.
Asynchronní lambda výrazy
Můžete snadno vytvořit lambda výrazy a příkazy, které zahrnují asynchronní zpracování pomocí asynchronní a vyčkání klíčová slova.Například model Windows Forms následující příklad obsahuje obslužnou rutinu události, která volá a čeká asynchronní metody, 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);
}
}
Stejnou obslužnou rutinu události lze přidat pomocí lambda asynchronní.Pokud chcete přidat tuto obslužnou rutinu, přidejte async modifikátor před lambda seznam parametrů, jak ukazuje následující příklad.
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);
}
}
Další informace o vytvoření a použití asynchronní metody viz Asynchronní asynchronní pro programování a očekávat (C# a Visual Basic).
Lambda výrazy standardní operátory dotazu
Mnoho standardních operátorů pro dotazování mají vstupní parametr, jehož typ je jedním z Func<T, TResult> řady obecných delegátů.Func<T, TResult> Delegátů pomocí parametrů typu definovat počet a typ vstupní parametry a návratový typ delegáta.FuncDelegáti jsou velmi užitečné pro uživatelem definované výrazy, které jsou použity pro každý prvek v sadě dat zapouzdření.Zvažte například následující typ delegáta:
public delegate TResult Func<TArg0, TResult>(TArg0 arg0)
Delegát může být vytvořena jako Func<int,bool> myFunc kde int je vstupní parametr, a bool je návratová hodnota.Vrácená hodnota je vždy podle poslední parametr typu.**Func<int, string, bool>**definuje delegáta, dva vstupní parametry int a stringa návratový typ bool.Následující Func delegáta při vyvolání, vrátí true nebo false označuje, zda vstupní parametr je roven 5:
Func<int, bool> myFunc = x => x == 5;
bool result = myFunc(4); // returns false of course
Lambda výraz lze také zadat, pokud je argument typ Expression<Func>, například ve standardních operátorů pro dotazování, které jsou definovány v System.Linq.Queryable.Při zadání Expression<Func> argument, bude kompilována lambda na strom výrazů.
Operátor standardního dotazu, Count metodu, je znázorněno zde:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
Kompilátor může odvodit typ vstupního parametru nebo jej explicitně také zadat.Ty celá počítá zejména lambda výraz (n) které při vydělených dvěma mít zbytek 1.
Následující metoda ohlásí obsahující všechny prvky v sekvenci numbers pole, které jsou na levé straně 9, protože je první číslo v sekvenci, která nesplňuje podmínku:
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Tento příklad ukazuje, jak zadat více vstupních parametrů uzavřením do závorek.Metoda vrátí všechny prvky pole čísla, dokud je zjištěna, jehož hodnota je menší než jeho pozici.Nezaměňujte operátor lambda (=>) s operátorem větší nebo rovna (>=).
var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);
Odvození typu proměnné v lambda výrazy
Při psaní lambda výrazy, často není nutné zadat typ pro vstupní parametry, protože kompilátor může odvodit typ na základě lambda subjektu, základní typ delegáta a další faktory, jak je popsáno ve specifikaci jazyka C#.Pro většinu standardních operátorů pro dotazování je první vstupní typ prvků ze zdrojové sekvence.Ano, pokud jsou dotazy IEnumerable<Customer>, pak vstupní proměnnou je odvozeno být Customer znamená mít přístup k vlastnosti a metody objektu:
customers.Where(c => c.City == "London");
Obecná pravidla pro lambda výrazy jsou následující:
Lambda musí obsahovat stejný počet parametrů jako typ delegáta.
Každý vstupní parametr lambda musí být implicitně převést na jeho odpovídající parametru delegáta.
Vrácená hodnota lambda (pokud existuje) musí být implicitně převést na návratový typ delegáta.
Všimněte si, že lambda výrazy, které samy o sobě nemají typ, protože common type system má vnitřní pojem "lambda výraz." Někdy je však vhodné neformálně hovořit "typu" lambda výraz.V těchto případech typ odkazuje na typ delegáta nebo Expression typ lambda výraz převedena.
Rozsah proměnné v Lambda výrazy
Lambda výrazy mohou odkazovat na vnější proměnné , které jsou v oboru v ohraničujícím metody nebo typu, ve kterém je definován lambda.Proměnné, které jsou zachyceny tímto způsobem jsou uloženy pro použití v lambda výrazu, i pokud proměnné by jinak přejít mimo rozsah a uvolňování.Vnější proměnné musí být jednoznačně přiřazena dříve, než mohou být spotřebovány ve lambda výrazu.Následující příklad ukazuje tato pravidla:
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();
}
}
Obor proměnných v lambda výrazy platí následující pravidla:
Zachycené proměnné nesmí být uvolňování dokud delegáta, který odkazuje, je mimo rozsah.
Nejsou viditelné v vnější metody proměnné zavedené v rámci lambda výrazu.
Lambda výraz nelze zachytit přímo ref nebo out z nadřazeného metody parametru.
Příkaz return v lambda výrazu nezpůsobí ohraničující metoda vrátí.
Lambda výraz nemůže obsahovat goto prohlášení, break prohlášení, nebo continue prohlášení, jehož cíl je mimo tělo, nebo v textu obsažené anonymní funkce.
Specifikace jazyka C#
Další informace naleznete v tématu Specifikace jazyka C#. Specifikace jazyka je úplným a rozhodujícím zdrojem pro syntaxi a použití jazyka C#.
Hlavní kapitoly knihy
Delegates, Events, and Lambda ExpressionsvC# 3.0 Cookbook, Third Edition: More than 250 solutions for C# 3.0 programmers
Viz také
Referenční dokumentace
Anonymní metody (Příručka programování C#)
Koncepty
Výraz stromů (C# a Visual Basic)