标题：Lambda表达式
类型
可以将此表达式分配给委托类型，如下所示： 
delegate int del(int i);
del myDelegate = x => { return x * x; };
int j = myDelegate(5); //j = 25
创建表达式目录树类型： 
using System.Linq.Expressions;
// ...
Expression<del> = x => x * x;
=> 运算符具有与赋值运算符 (=) 相同的优先级，并且是右结合运算符。 
Lambda 用在基于方法的 LINQ 查询中，作为诸如 Where 和 Where 等标准查询运算符方法的参数。 
使用基于方法的语法在 Enumerable 类中调用 Where 方法时（像在 LINQ to Objects 和 LINQ to XML 中那样），参数是委托类型 System..::.Func<(Of <(T, TResult>)>)。使用 Lambda 表达式创建委托最为方便。例如，当您在 System.Linq..::.Queryable 类中调用相同的方法时（像在 LINQ to SQL 中那样），则参数类型是 System.Linq.Expressions..::.Expression<Func>，其中 Func 是包含至多五个输入参数的任何 Func 委托。同样，Lambda 表达式只是一种用于构造表达式目录树的非常简练的方式。尽管事实上通过 Lambda 创建的对象的类型是不同的，但 Lambda 使得 Where 调用看起来类似。 
在前面的示例中，请注意委托签名具有一个 int 类型的隐式类型输入参数，并返回 int。可以将 Lambda 表达式转换为该类型的委托，因为该表达式也具有一个输入参数 (x)，以及一个编译器可隐式转换为 int 类型的返回值。（以下几节中将对类型推理进行详细讨论。）使用输入参数 5 调用委托时，它将返回结果 25。 
在 is 或 as 运算符的左侧不允许使用 Lambda。 
适用于匿名方法的所有限制也适用于 Lambda 表达式。有关更多信息，请参见匿名方法（C# 编程指南）。
特殊
下列规则适用于 Lambda 表达式中的变量范围： 
捕获的变量将不会被作为垃圾回收，直至引用变量的委托超出范围为止。 
在外部方法中看不到 Lambda 表达式内引入的变量。 
Lambda 表达式无法从封闭方法中直接捕获 ref 或 out 参数。 
Lambda 表达式中的返回语句不会导致封闭方法返回。 
Lambda 表达式不能包含其目标位于所包含匿名函数主体外部或内部的 goto 语句、break 语句或 continue 语句。
Lambda表达式的本质是“匿名方法”，即当编译我们的程序代码时，“编译器”会自动将“Lambda表达式”转换为“匿名方法”，如下例：
string[] names = { "agen", "balen", "coure", "apple" };
string[] findNameA = Array.FindAll<string>(names, delegate(string v) { return v.StartsWith("a"); });
string[] findNameB = Array.FindAll<string>(names, v => v.StartsWith("a"));
上面中两个FindAll方法的反编译代码如下：
string[] findNameA = Array.FindAll<string>(names, delegate (string v) { return v.StartsWith("a"); } );
string[] findNameB = Array.FindAll<string>(names, delegate (string v) { return v.StartsWith("a"); } );
从而可以知道“Lambda表达式”与“匿名方法”是可以划上等号的，只不过使用“Lambda表达式”输写代码看上去更直观漂亮，不是吗?
Lambda表达式的语法格式： 参数列 => 语句或语句块
其中“参数列”中可包含任意个参数(与委托对应），如果参数列中有0个或1个以上参数，则必须使用括号括住参数列，如下：
() => Console.Write("0个参数")
I => Console.Write("1个参数时参数列中可省略括号，值为：{0}",i)
(x,y) => Console.Write("包含2个参数，值为：{0}*{1}",x,y)
而“语句或语句块”中如果只有一条语句，则可以不用大括号括住否则则必须使用，如下：
I => Console.Write("只有一条语句")
I => { Console.Write("使用大括号的表达式"); }
//两条语句时必须要大括号
I => { i++;Console.Write("两条语句的情况"); }
如果“语句或语句块”有返回值时，如果只有一条语句则可以不输写“return”语句，编译器会自动处理，否则必须加上，如下示例：
class Test
{
delegate int AddHandler(int x, int y);
static void Print(AddHandler add)
{
Console.Write(add(1, 3));
}
static void Main()
{
Print( (x, y) => x + y );
Print( (x, y) => { int v = x * 10; return y + v; } );
Console.Read();
}
}
“Lambda表达式”是委托的实现方法，所以必须遵循以下规则：
1）“Lambda表达式”的参数数量必须和“委托”的参数数量相同；
2）如果“委托”的参数中包括有ref或out修饰符，则“Lambda表达式”的参数列中也必须包括有修饰符；
例子：
class Test
{
delegate void OutHandler(out int x);
static void Print(OutHandler test)
{
int i;
test(out i);
Console.Write(i);
}
static void Main()
{
Print( (out int x) => x = 3);
Console.Read();
}
}
注： 如果包括有修饰符，则“Lambda表达式”中的参数列中也必须加上参数的类型
3）如果“委托”有返回类型，则“Lambda表达式”的“语句或语句块”中也必须返回相同类型的数据；
4）如果“委托”有几种数据类型格式而在“Lambda表达式”中“编译器”无法推断具体数据类型时，则必须手动明确数据类型。
例子：
(错误代码）
class Test
{
delegate T AddHandler<T>(T x, T y);
static void Print(AddHandler<int> test)
{
Console.WriteLine("int type:{0}", test(1, 2));
}
static void Print(AddHandler<double> test)
{
Console.WriteLine("double type:{0}", test(1d, 2d));
}
static void Main()
{
Print( (x, y) => x + y );
Console.Read();
}
}
当我们编译以下代码时，编译器将会显示以下错误信息：
在以下方法或属性之间的调用不明确:
“ConsoleApplication1.Test.Print(ConsoleApplication1.Test.AddHandler<int>)”和“ConsoleApplication1.Test.Print(ConsoleApplication1.Test.AddHandler<double>)”
所以我们必须明确数据类型给编译器，如下：
Print( (int x, int y) => x + y );
这样我们的代码就能编译通过了:)