1、什么是lambda表达式
x=>x*x;
(x,y)=>x+y;
参数列中可包含任意个参数(与委托对应),如果参数列中有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("两条语句的情况"); };
3、实例说明
public class Student { //这里为了简便就不用属性了 public int id; public string name; public int age; public int classId;//假设有一个班级编号 public Student(int id, string name, int age, int classId) { this.id = id; this.name = name; this.age = age; this.classId = classId; } }
新建一个aspx的页面,拖入控件button和Label:
<asp:Button ID="Button2" runat="server" Text="lambda表达式的运用" onclick="Button2_Click" /> <br /> <asp:Label ID="Label2" runat="server" Text=""></asp:Label>
在页面的cs文件中添加排序的方法(定义委托):
//使用委托,当然这种可以用泛型来解决 public delegate bool CompareDelegate(Student s1, Student s12); private void Sort(Student[] s,CompareDelegate method) { for (int i = 0; i < s.Length - 1; i++)//控制轮数 { for (int j = 0; j < s.Length - 1 - i; j++)//控制交换次数 { if (method(s[j],s[j+1]))//根据age排名 { Student temp = s[j]; s[j] = s[j + 1]; s[j + 1] = temp; } } } }
在button的响应函数中添加响应函数:
//lambda表达是实现 Sort(s,((Student s1,Student s2)=>s1.id > s2.id)); //Sort(s, ((Student s1, Student s2) => s1.age > s2.age));
运行结果如下:
//匿名方法实现 Sort(s, delegate(Student s1, Student s2) { return s1.id > s2.id; }); //Sort(s, delegate(Student s1, Student s2) //{ // return s1.age > s2.age; //}); private bool CompareById(Student s1, Student s2)//具体实现 { return s1.id > s2.id; } private bool CompareByAge(Student s1, Student s2) { return s1.age > s2.age; }
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(); } }
C# 2.0规范中提到的匿名方法规范同样适用于Lambda表达式。Lambda表达式是匿名方法在功能行上的超集,提供了下列附加的功能:
Lambda表达式允许省略参数类型并对其进行推断,而匿名方法要求参数类型必须显式地声明。
Lambda表达式体可以是表达式或语句块,而匿名方法体只能是语句块。
在类型参数推导和方法重载抉择时,Lambda表达式可以被作为参数传递。
以一个表达式作为表达式体的Lambda表达式可以被转换为表达式树。
和匿名方法表达式类似,Lambda表达式可以归类为一种拥有特定转换规则的值。这种值没有类型,但可以被隐式地转换为一个兼容的委托类型。特别地,当满足下列条件时,委托类型D兼容于Lambda表达式L:
D和L具有相同数量的参数;
如果L具有显式类型的参数列表,D中每个参数的类型和修饰符必须和L中相应的参数完全一致;
如果L具有隐式类型的参数列表,则D中不能有ref或out参数;
如果D具有void返回值类型,并且L的表达式体是一个表达式,若L的每个参数的类型与D的参数一致,则L的表达式体必须是一个可接受为statement-expression的有效表达式;
如果D具有void返回值类型,并且L的表达式体是一个语句块,若L的每个参数的类型与D的参数一致,则L的表达式体必须是一个有效语句块,并且该语句块中不能有带有表达式的return语句;
如果D的返回值类型不是void,并且L的表达式体是一个表达式,若L的每个参数的类型与D的参数一致,则L的表达式体必须是一个可以隐式转换为D的返回值类型的有效表达式;
如果D的返回值类型不是void,并且L的表达式体是一个语句块,若L的每个参数的类型与D的参数一致,则L的表达式体必须是一个有效的语句块,该语句块不能有可达的终点(即必须有return语句),并且每个return语句中的表达式都必须能够隐式转换为D的返回值类型。
许多标准查询运算符都具有输入参数,其类型是泛型委托的 Func<T, TResult> 系列的其中之一。 Func<T, TResult> 委托使用类型参数定义输入参数的数目和类型,以及委托的返回类型。 Func 委托对于封装应用于一组源数据中每个元素的用户定义表达式非常有用。 例如,假设有以下委托类型:
public delegate TResult Func<TArg0, TResult>(TArg0 arg0)
可以将委托实例化为 Func<int,bool> myFunc,其中 int 是输入参数,bool 是返回值。 始终在最后一个类型参数中指定返回值。 Func<int, string, bool> 定义包含两个输入参数(int 和 string)且返回类型为 bool 的委托。 在调用下面的 Func 委托时,该委托将返回 true 或 false 以指示输入参数是否等于 5:
Func<int, bool> myFunc = x => x == 5; bool result = myFunc(4);