C# Lambda表达式
lambda表达式是一个未命名的方法,代替一个委托实例。
给定以下委托类型:
1 |
delegate int Converter (int i); |
我们可以如下分配和调用lambda表达式x => x * x:
1 2 |
Converter sqr = x => x * x; Console.WriteLine (sqr(3)); // 9 |
lambda表达式具有以下形式:
1 |
(parameters) => expression |
1 2 |
We can omit the parentheses if and only if there is exactly one parameter of an inferable type. |
在我们的示例中,有一个参数, x
,表达式为 x * x
:
1 |
x => x * x; |
lambda表达式的每个参数都对应一个委托参数,表达式的类型对应于委托的返回类型。
在上面的代码中, x
对应于参数 i
,表达式 x * x
对应于返回类型 int
,因此它与 Converter
委托兼容,如下所示:
1 |
delegate int Converter (int i); |
lambda表达式的代码可以是语句块而不是表达式。
1 |
x => { return x * x; }; |
Lambda表达式最常用于Func和Action委托。
我们可以重写上面的代码如下:
1 |
Func<int,int> sqr = x => x * x; |
下面是一个接受两个参数的表达式示例:
1 2 |
Func<string,string,int> totalLength = (s1, s2) => s1.Length + s2.Length; int total = totalLength ("a", "the"); |
捕获外部变量
lambda表达式可以引用定义它的方法的局部变量和参数。
例如:
1 2 3 4 5 |
static void Main(){ int factor = 2; Func<int, int> multiplier = n => n * factor; Console.WriteLine (multiplier (3)); // 6 } |
由lambda表达式引用的外部变量称为捕获变量。
捕获变量的lambda表达式称为闭包。
捕获的变量在实际调用委托时求值,而不是在捕获变量时求值:
1 2 3 4 |
int factor = 2; Func<int, int> multiplier = n => n * factor; factor = 3; Console.WriteLine (multiplier (3)); // 9 |
Lambda表达式可以更新捕获的变量:
1 2 3 4 5 6 |
int outerVariable = 0; Func<span class="hljs-tag"><<span class="hljs-name">int</span>></span> myLambda = () => outerVariable++; Console.WriteLine (myLambda()); // 0 Console.WriteLine (myLambda()); // 1 Console.WriteLine (outerVariable); // 2 |
匿名方法
要编写匿名方法,请包括delegate关键字,随后可以包含参数声明,然后是方法体。
例如,给这个代理:
1 |
delegate int Converter (int i); |
我们可以写和调用匿名方法如下:
1 2 |
Converter sqr = delegate (int x) {return x * x;}; Console.WriteLine (sqr(3)); // 9 |
第一行在语义上等同于以下lambda表达式:
1 |
Converter sqr = (int x) => {return x * x;}; |
或者简单为:
1 |
Converter sqr = x => x * x; |
匿名方法以与lambda表达式相同的方式捕获外部变量。