设为首页 加入收藏

TOP

C#方法组转换和匿名方法
2015-03-04 22:51:17 来源: 作者: 【 】 浏览:41
Tags:方法 转换 匿名

前面的文章介绍过,C# 1.0中出现委托这个核心概念,在C# 2.0中,委托得到了很大的改进。C# 2.0中委托的改进为C# 3.0中的新特性提供了铺垫,当我们了解了匿名方法后,Lambda的学习就会变得相对容易。


下面就看看C# 2.0中委托的改进。


在C# 1.0中,如果要创建一个委托实例,就必须同时指定委托类型和符合委托签名的方法。但是,在C# 2.0中,支持了方法组转换,也就是说我们可以从方法组到一个兼容委托类型的隐式转换。所谓"方法组"(method group),其实就是一个方法名。


看一个例子:


通过方法组转换,繁琐的委托实例创建得到了简化。


根据C# 1.0中了解到的知识,当我们创建一个委托实例的时候,我们需要找到一个跟委托类型签名一致的方法,用这个方法来实例化一个委托对象。


看看前面的字符串反转的例子,可能"ReverseString"这个方法在程序中只会使用一次,但是为了创建委托实例,这个方法必须要存在。


在C# 2.0中引入了匿名方法,所以有了更简单的方式实现上面的例子:


从上面可以看到,匿名方法就是通过delegate关键字以及参数列表和具体语句块的实现。


所以说,如果用来实例化委托的方法比较简单,并且这个方法在其他地方使用的频率很低时,这时候就可以考虑用匿名方法来进行简化。


如果你对匿名方法仍有疑惑,建议你看看上面例子的IL代码。


在Main函数的IL代码中,可以看到编译器为我们生成了一个名为"

b__0"的方法,方法接受一个string类型的参数。


当我们查看"

b__0"方法的IL代码后,可以看到这个方法就是我们在匿名方法的语句块中定义的操作。


匿名方法的实现原理就是:编译器将在匿名方法所在的类,为每个匿名方法都创建了一个方法。编译器创建的这些方法只在IL代码中有效,在C#代码中是无效的,所以C#代码不能直接使用这些方法。


其实,匿名方法更常用的地方是把匿名方法当作一个参数传递给另一个方法。大家肯定都知道List有一个FindAll的方法来查找符合条件的item,这里FindAll的参数就是一个过滤条件的委托。


说到了这里,我们就看看系统帮我们定义的委托,在C#中,Action、Func和Predicate是系统定义的委托,我们可以直接使用。上面的FindAll的参数就是一个Predicate的泛型委托。


Action是无返回值的泛型委托,Action委托可以支持至少0个参数,至多16个参数。


例如:


对于前面的字符串反转的例子,我们可以使用Action委托进一步简化,这样我们连"ReverseStringHandler"这个委托也省略了:


前面看到Action委托是没有返回值的,为了解决我们有时可能需要返回值的问题,系统中又出现了Func委托。


Func是有返回值的泛型委托,其中TResult就代表返回值的类型()。Func委托可以支持至少0个参数,至多16个参数(Func)。


例如:


看个简单的例子:


predicate 是返回bool型的泛型委托,常常结合集合类的查询使用;Predicate有且只有一个参数,返回值固定为bool。


Predicate原型:public delegate bool Predicate (T obj)


在前面结合查询的例子中,我们直接把匿名方法"delegate(int n){return n>6;}"传给了FindAll方法。


其实也可以写成,


在有些情况下,我们并不需要委托参数,那么匿名方法可以进一步省略参数列表,只需要使用一个delegate关键字,加上作为方法的操作使用的代码块。


看一个简单的代码段:


注意,这个"参数通配"(paremeter wildcarding)的特性并不能适用所有的情况,如果匿名方法能够转换成多个委托类型,那么我们就需要给编译器提供更多的信息


举个例子,线程的构造函数设计两个委托类型,一个有参数,一个无参数。


所以,当我们通过下面的语句创建线程的时候,前两条语句没有问题,但是第三条语句会有一个错误。


因为第三条语句中的匿名方法可以转换成多个委托类型,编译器就不知道怎么处理了,所以,我们需要显示给出参数列表。



本篇文章介绍了C# 2.0中委托的改进,通过方法组转换和匿名方法,可以简化程序。


同时,看到了系统定义的三个委托类型,所以有些时候我们可以不用创建自己的委托;但是要这个权衡,如果我们要经常使用一个特定类型的委托,那还是建议定义一个有意义更加明显的委托类型。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C#匿名方法中的变量 下一篇C#可空类型

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: