Lambda表达式提供一种更精简的方式来写匿名方法,其语法格式为:
Ø 表达式:
赋值表达式
非赋值表达式
Ø 非赋值表达式:
条件表达式
Lambda表达式
查询表达式
Ø Lambda表达式:
(Lambda参数列表可选)=>Lambda表达式体
隐式类型Lambda参数=> Lambda表达式体
Ø Lambda参数列表:
显式类型Lambda参数列表
隐式类型Lambda参数列表
Ø 显式类型Lambda参数列表:
显式类型Lambda参数
显式类型Lambda参数列表,显式类型Lambda参数
Ø 显式类型Lambda参数:
参数修饰符可选 类型 标识符
Ø 隐式类型Lambda参数列表
隐式类型Lambda参数
隐式类型Lambda参数列表,隐式类型Lambda参数
Ø 隐式类型Lambda参数:
标识符
Ø Lambda表达式体:
表达式
语句块
示例:
x => x + 1; // Implicitly typed, expression body
x => { return x + 1; }; // Implicitly typed, statement body
(int x) => x + 1; // Explicitly typed, expression body
(int x) => { return x + 1; }; // Explicitly typed, statement body
() => Console.WriteLine("OK"); //无参数列表
(x,y) => x*y; // Multiple parameters
注意:
1 如果是隐式类型,并且只有一个参数时,可以省略括号,如(x) => x + 1,可以简写成x => x + 1
2 隐式类型和显式类型不能混合使用
当代理类型和Lambda表达式满足下列条件时,我们说它们是兼容的,也就是可以将Lambda表达式赋值给该代理类型:
1 代理类型和Lambda表达式具有相通数量的参数;
2 如果Lambda表达式是显式类型参数列表,那么每一个参数的类型要和对应的代理类型的参数的类型和修饰符相同;如果是隐式类型参数列表,那么代理类型中不能有ref和out的参数,根据Lambda表达式体推导出的参数类型要和代理类型的参数一致。
3 如果Lambda表达式体是一个语句块,并且代理类型的返回值是void,那么语句块中不能包含有包含返回值的return语句;如果代理类型的返回值不是void,那么语句块必须是包含返回值的return语句,而且返回值的类型要和代理类型的返回值一致。
4 如果Lambda表达式体是一个表达式,并且代理类型的返回值是void,那么表达式必须是能作为语句的表达式(只能是赋值表达式,对对象或函数的调用,new 表达式,变量的++,--操作表达式之一);如果代理类型的返回值不是void,那么根据表达式推导出的类型必须能和代理类型的返回值类型一致。
示例:
public delegate R Func<T,R>(T t);
public delegate void F2();
public delegate R F3<T,R>(T t,R r);
Func<int, int> a = x => x + 1;
F2 b = () => Console.WriteLine("OK");
F3<int, int> c = (x,y) => x*y;
下例将会出现编译错误:
public delegate void F3<T,R>(T t,R r);
F3<int, int> c = (x,y) => x*y;//Compile error: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
当Lambda表达式传递给一个没有指定类型参数的泛型方法时,.Net架构将根据表达式来推导出相应的类型参数,例如:
public static class Extensions
{
public static IEnumerable<S> MySelect<T, S>(this IEnumerable<T> source,Func<T, S> selector)
{ foreach (T element in source) yield return selector(element); }
}
var contacts = new[] { new {Name = "Chris Smith",PhoneNumbers = new[]{ "206-555-0101", "425-882-8080" }},
new {Name = "Bob Harris",PhoneNumbers = new[] { "650-555-0199" }}};
IEnumerable<string> name = contacts.MySelect(j => j.Name);
在这里MySelect是一个扩展函数,所以contacts.MySelect(j => j.Name)运行时将翻译成Extensions.MySelect(contacts,j => j.Name),在这里T就是包含Name和电话号码的匿名类型,所以S就是string 类型。
如果存在两个相同名称的带有Lambda表达式为参数的方法,在隐式转换过程中输入参数和返回值的类型以最容易转换为原则进行匹配