1 前言
本系列会将【委托】 【匿名方法】【Lambda表达式】 【泛型委托】 【表达式树】 【事件】等基础知识总结一下。(本人小白一枚,有错误的地方希望大佬指正)
系列4:细说泛型委托
系列5:细说表达式树
系列6:细说事件
还是用大佬的文章来震场吧,“随着.net版本的不升级,新版本总要区别于旧版本吧,不然微软的工程师怎么向他们的老大交差呀?所以微软又来玩新花样了。”
这次我们提前贴代码来体验一下泛型委托与一般委托和匿名方法实现委托和Lambda 表达式实现委托的区别。
class Program { static void Main(string[] args) { //方法一: Func<int, int, int> cAdd1 = (int x, int y) => { return x + y; }; int result1 = cAdd1(3, 6); //方法二: Func<int, int, int> cAdd2 = (x, y) => { return x + y; }; int result2 = cAdd2(4, 6); //方法三: Func<int, int, int> cAdd3 = (x, y) => x + y; int result3 = cAdd2(5, 6); Console.WriteLine("{0},{1},{2}",result1, result2, result3); Console.ReadKey(); } }
不管是匿名方法还是Lambda表达式,完成一个委托的应用,都逃不过两个步骤,一步是定义一个委托,另一步是用一个方法来实例化一个委托。 微软干脆把这两步都合成一步来走了。用Func来简化一个委托的定义。
至此,一个委托的应用就可用 Func<int, int, int> cAdd3 = (x, y) => x + y; 这样一句话来完成了,其中的Func就是所谓的泛型委托。
好了,震场完毕,接着我们来解剖一下泛型委托。
2 什么是泛型委托
泛型委托,什么是泛型,这个概念我也会在之后做出总结,这里不做很深层次的讨论,重点是讨论泛型和委托如何配合使用,其实泛型这个概念在这里也不会对我们对委托的理解有太大的影响,我们只要大概知道泛型就是一种动态的类型,它在使用时可以代表任意类型,下面我们再来回顾一下我们是如何定义普通委托的:
public delegate int 委托名(int a, int b);
这是委托的定义,它的定义有这几个特点,(1)可以用访问修饰符修饰。(2)delegate关键字。(3)有返回值和参数。
我们之前也说了,委托是一种类型,与之对应的方法必须和它具有相同的签名,即相同的参数个数,相同的参数类型和相同的返回值类型。我们回顾了普通委托之后再来看一下泛型委托的定义:
public delegate T 委托名<T>(T a, T b);
但是这样还是不简单啊,其实微软早已为我们定义好了一套泛型委托供我们使用,以免我们在自己使用时还繁琐重复的去定义它,他们分别是Action,Func和Predicate。
3 泛型委托的使用
接下来介绍一下微软定义好的Action,Func。
Func是一种委托,这是在3.5里面新增的,2.0里面我们使用委托是用Delegate,Func位于System.Core命名空间下,使用委托可以提升效率,例如在反射中使用就可以弥补反射所损失的性能。
Action<T>和Func<T,TResult>的功能是一样的,只是Action<T>没有返类型,
Func<T,T,Result>:有参数,有返回类型
Action,则既没有返回也没有参数,
Func<T,TResult>的表现形式分为以下几种:
- Func<T,TResult>
- Func<T,T1,TResult>
- Func<T,T1,T2,TResult>
- Func<T,T1,T2,T3,TResult>
- Func<T,T1,T2,T3,T4,TResult>
分别说一下各个参数的意义,TResult表示
委托所返回值 所代表的类型, T,T1,T2,T3,T4表示委托所调用的方法的参数类型,
以下是使用示例:
Func<int, bool> myFunc = null;//全部变量 myFunc = x => CheckIsInt32(x); //给委托封装方法的地方 使用了Lambda表达式 private bool CheckIsInt32(int pars)//被封装的方法 { return pars == 5; } bool ok = myFunc(5);//调用委托
但是如果我们需要所封装的方法不返回值,增么办呢?就使用Action!
可以使用Action<T1, T2, T3, T4>委托以参数形式传递方法,而不用显式声明自定义的委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。(在 C# 中,该方法必须返回 void。在 Visual Basic 中,必须通过 Sub…End Sub 结构来定义它。)通常,这种方法用于执行某个操作。
使用方法和Func类似!
Action:既没有返回,也没有参数,使用方式如下:
Action action = null;//定义action action = CheckIsVoid;//封装方法,只需要方法的名字 action();//调用
总结:
使用Func<T,TResult>和Action<T>,而不使用Delegate其实都是为了简化代码,使用更少的代码达到相同的效果,不需要我们显示的声明一个委托。
Func<T,TResult>的最后一个参数始终是返回类型,而Action<T>是没有返回类型的,而Action是没有返回类型和参数输入的。
4 总结
弄明白这些,其实就已经够简便了,但是为了引申一下,下篇文章讲一下表达式树。
参考文献:
MSDN:http://msdn.microsoft.com/zh-cn/library/bb534303(VS.95).aspx
https://www.cnblogs.com/xcj26/p/3536082.html