4.C#编程指南-匿名函数
匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用。可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数。
共有两种匿名函数:
1.Lambda表达式
2.匿名方法
C#委托的发展
class Test { delegate void TestDelegate(string s); static void M(string s) { Console.WriteLine(s); } static void Main(string[] args) { TestDelegate testDelA = new TestDelegate(M); TestDelegate testDelB = delegate(string s) {Console.WriteLine(s); }; TestDelegate testDelC = (x) => { Console.WriteLine(x); }; testDelA("Hello. My name is M and I write lines."); testDelB("That's nothing. I'm anonymous and "); testDelC("I'm a famous author."); } } /* Output: Hello. My name is M and I write lines. That's nothing. I'm anonymous and I'm a famous author. */
Lambda表达式
"Lambda表达式"是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。
所有Lambda表达式都使用Lambda运算符=>,该运算符读为“goes to”。该Lambda运算符的左边是输入参数(如果有),右边则包含表达式或语句块。
=>运算符具有与赋值运算符(=)相同的优先级,并且是右结合运算符。
Lambda在基于方法的LINQ查询中用作标准查询运算方法(如Where)的参数。
使用基于方法的语法在Enumerable类中调用Where方法时,参数是委托类型System.Func(Of T,TResult)。使用Lambda表达式创建委托最为方便。
在is或as运算符的左侧不允许使用Lambda。
1.基本形式:
(input parameters) => expression
2.只有在Lambda有一个输入参数时,括号才是可选的;否则括号是必需的。两个或更多输入参数由括号中的逗号分隔:
(x,y) => x == y
3.有时,编译器难于或无法推断输入类型。如果出现这种情况,您可以按以下方式显式指定类型:
(int x,string s) => s.Length > x
4.使用空括号指定零个输入参数:
() => SomeMethod()
Lambda语句
Lambda语句与Lambda表达式类似,只是语句在大括号中:
(input parameters) => {statement;}
Lambda语句的主体可以包含任意数量的语句;但是,实际上通常不会多于两个或三个语句。
带有标准查询运算符的Lambda
许多标准查询运算符都具有输入参数,其类型是泛型委托的Func(Of T,TResult)系列的其中之一。Func(Of T,TResult)委托使用类型参数定义输入参数的数目和类型,以及委托的返回类型。
例如,假设有以下委托类型:
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); //returns false of course
匿名方法
在2.0之前的C#版本中,声明委托的唯一方法是使用命名方法。C#2.0引入了匿名方法,而在C#3.0及更高版本中,Lambda表达式取代了匿名方法,作为编写内联代码的首选方式。有一种情况下,匿名方法提供了Lambda表达式中所没有的功能。您可使用匿名方法来忽略参数列表。这意味着匿名方法可以转换为具有各种签名的委托。这对于Lambda表达式来说是不可能的。
要将代码块传递为委托参数,创建匿名方法则是唯一的方法。
//例1 button1.Click += delegate(System.Object o, System.EventArgs e) { System.Windows.Forms.MessageBox.Show("Click!"); }; //例2 delegatevoid Del(int x); Del d = delegate(int k) { /* ... */ };
下面的示例演示实例化委托的两种方法:
1.使委托与匿名方法关联。
2.使委托与命名方法(DoWork)关联。
delegate void Printer(string s); class TestClass { static void Main() { //1.使委托与匿名方法关联. Printer p = delegate(string j) { System.Console.WriteLine(j); }; p("The delegate using the anonymous method is called."); //2.使委托与命名方法 (DoWork) 关联。 p = new Printer(TestClass.DoWork); p("The delegate using the named method is called."); } static void DoWork(string k) { System.Console.WriteLine(k); } } /* Output: The delegate using the anonymous method is called. The delegate using the named method is called. */