把Lambda表达式用于匿名方法
下面看一下Lambda表达式。Lambda表达式是简化匿名方法的语法的一种方式。实际上,Lambda表达式还有其他用处,但为了简单起见,本节只介绍Lambda表达式的这个方面。使用Lambda表达式可以重写上一节最后的一段代码,如下所示:
myTimer.Elapsed += (source, e) => Console.WriteLine(
"Event handler called after {0} milliseconds.",
(source as Timer).Interval);
这段代码初看上去有点让人摸不着头脑(除非很熟悉所谓的函数化编程语言,如Lisp或Haskell)。但如果仔细观察,就会看出或至少推断出代码是如何工作的,它与所替代的匿名方法有什么关系。
Lambda表达式由3个部分组成:
• 放在括号中的参数列表(未类型化)
• => 运算符
• C#语句
使用本章前面“匿名类型”一节中介绍的逻辑,从上下文推断出参数的类型。=>
运算符只是把参数列表与表达式体分开。在调用Lambda表达式时,执行表达式体。
编辑器会提取这个Lambda表达式,创建一个匿名方法,其工作方式与上一节中的匿名方法相同。其实,它会被编译为相同或相似的CIL代码。
为了说明Lambda表达式中的内容,下面列举一个例子。
namespace Ch14Ex06
{
delegate int TwoIntegerOperationDelegate(int paramA, int paramB);
class Program
{
static void PerformOperations(TwoIntegerOperationDelegate del)
{
for(int paramAVal = 1; paramAVal <= 5; paramAVal++)
{
for(int paramBVal = 1; paramBVal <= 5; paramBVal++)
{
int delegateCallResult = del(paramAVal, paramBVal);
Console.Write("f({0},{1})={2}",
paramAVal, paramBVal, delegateCallResult);
if(paramBVal != 5)
{
Console.Write(", ");
}
}
Console.WriteLine();
}
}
static void Main(string[] args)
{
Console.WriteLine("f(a, b) = a + b:");
PerformOperations((paramA, paramB) => paramA + paramB);
Console.WriteLine();
Console.WriteLine("f(a, b) = a * b:");
PerformOperations((paramA, paramB) => paramA * paramB);
Console.WriteLine();
Console.WriteLine("f(a, b) = (a - b) % b:");
PerformOperations((paramA, paramB) => (paramA - paramB) % paramB);
Console.ReadKey();
}
}
}
示例的说明 这个示例使用Lambda表达式生成函数,用来在两个输入参数上执行指定的处理,并返回结果。接着这些函数操作25对值,把结果输出到控制台上。 首先定义一个委托类型TwoIntegerOperationDelegate,表示一个方法,该方法有两个int参数,返回一个int结果:
delegate int TwoIntegerOperationDelegate(int paramA, int paramB);
在以后定义Lambda表达式时使用这个委托类型。这些Lambda表达式编译为方法,其返回类型和参数匹配这个委托类型,如稍后所述。
接着添加方法PerformOperations(),它带有一个TwoIntegerOperationDelegate类型的参数:
static void PerformOperations(TwoIntegerOperationDelegate del)
{
这个方法的含义是,可以给它传送一个委托实例(或者匿名方法,或者Lambda表达式,因为这些结构都会编译为委托实例),该方法会用一组值调用委托实例所表示的方法:
for(int paramAVal = 1; paramAVal <= 5; paramAVal++)
{
for(int paramBVal = 1; paramBVal <= 5; paramBVal++)
{
int delegateCallResult = del(paramAVal, paramBVal);
接着把参数和结果输出到控制台上:
Console.Write("f({0},{1})={2}",
paramAVal, paramBVal, delegateCallResult);
if(paramBVal != 5)
{
Console.Write(", ");
}
}
Console.WriteLine();
}
}
在Main()方法中,创建了3个Lambda表达式,使用它们依次调用PerformOperations()。第一个调用如下所示:
Console.WriteLine("f(a, b) = a + b:");
PerformOperations((paramA, paramB) => paramA + paramB);
这里使用的Lambda表达式如下:
(paramA, paramB) => paramA + paramB
这个Lambda表达式分为3部分:
(1)参数定义部分。这里有两个参数paramA和paramB。这些参数都是未类型化的,因此编译器可以根据上下文推断出它们的类型。在这个例子中,编译器可以确定,PerformOperations()方法调用需要一个TwoIntegerOperationDelegate类型的委托。这个委托类型有两个int参数,所以根据推断,paramA和paramB都是int类型的变量。
(2)=> 运算符。它把Lambda表达式的参数与表达式体分开。
(3)表达式体。它指定了一个简单操作:把paramA和paramB加起来。注意,不需要指定这是返回值。编译器知道,要创建可以使用TwoIntegerOperationDelegate的方法,这个方法就必须有int返回类型。根据指定的操作,paramA + paramB等于一个int类型的值,且没有提供额外的信息,所以编译器推断,这个表达式的结果就是方法的返回类型。
接着,就可以把使用这个Lambda表达式的代码扩展到下面使用匿名方法的代码中:
Console.WriteLine("f(a, b) = a + b:");
PerformOperations(delegate(int paramA, int paramB)
{
return paramA + paramB;
});
其余代码以相同方式使用两个不同的Lambda表达式来执行操作:
Console.WriteLine();
Console.WriteLine("f(a, b) = a b:");
PerformOperations((paramA, paramB) => paramA paramB);
Console.WriteLine();
Console.WriteLine("f(a, b) = (a - b) % b:");
PerformOperations((paramA, paramB) => (paramA - paramB) % paramB);
Console.ReadKey();
最后一个Lambda表达式涉及较多计算,但并不比其他Lambda表达式更复杂。Lambda表达式的语法允许执行更复杂的操作,如稍后所述。
```