一些武侠小说里的大人物,为了争夺武林盟主,号召天下,经常闭关修炼一段时间,闭关期间只能接触送饭的人,并且关外还有很多守卫的人员。还有,无论是篮球还是足球运动员,他们在真正接触球之前,都必须做很长一段时间的身体素质锻炼,像长跑之类。
如果我们想成为程序界的武林至尊,那么我们也必须得闭关修炼,仔细修炼基本功。
那么我们做Windows移动开发的程序员们的基本功是什么呢?其实,基本功有很多,最重要的是逻辑思维和解决问题的能力,话又说回来,逻辑思维和解决问题的能力从何而来呢?不断的做、练,熟能生巧在程序界内是最能得到体现的了。
我们这些Windows移动开发的“屌丝们”该做、练些什么呢?我是用C#做Windows移动开发的,所以我所用的武器是C#,所有的招数也都是C#打出来的,在闭关这个环节,我主要修炼委托、继承、多态、垃圾回收以及泛型,这一次,我主要练习C#中的委托。
1.1 什么是委托
学过C和C++的人都知道指针,当我们想把方法来作为参数来传递的时候,我们可以传递函数的指针,也就是函数的内存地址,这样做会导致类型不安全,很难控制,在C#中,为了避免这个问题,推出了委托,委托是一个特殊类型的对象,它和类应该是平级别的,也就是说,委托可以声明在命名空间内,也可以在类内部声明,委托也是一个内存地址,但它是类型安全的。
1.1.1 委托的声明
委托和类一样,需要提前声明,声明的格式:
delegate int DGetResult(int a,int b);
1.1.2 委托实例的声明
声明好一个委托后,我们需要给他声明一个方法实例,方法实例必须与委托保持签名相同,即方法返回值类型和委托一致,方法参数的类型、个数、顺序和委托一致。上面委托的一个实例方法:
private int GetAddResult(int a,int b)
{
return a+b;
}
下面,我们就可以在Main函数里面调用这个委托了,调用委托和类一样,也必须申请一个委托对象,通过对象调用委托,如下:
DGetResult getResult = GetAddResult; //此处不需要加参数和括号,把委托对象的地址指向方法
Console.WriteLine(getResult(2,4).ToString()); //通过委托对象执行
Console.ReadKey();
1.1.3 委托对象的赋值、方法的加减
一个委托对象可以同时调用多个方法,我们可以给一个委托对象添加多个实例方法,如下:
int GetMinusResult(int a, int b) //新实例方法
{
return a - b;
}
在Main函数中调用方法:
getResult +=GetMinusResult;
Console.WriteLine(getResult(2,4).ToString());
运行结果是-2,如果我们在方法GetAddResult内部加断点执行,我们会发现,方法GetAddResult也被执行了。
既然委托对象可以添加方法,那么委托对象也可以删减方法。
gerResult-=GetMinusResult;
Console.WriteLine(getResult(2,4).ToString());
这回程序的运行结果就是6了。
1.1.4多播委托方法受阻问题
其实,我们上面所使用的委托叫多播委托,多播委托会有一个问题,当多播委托方法组中的前面的方法出现异常,那么委托对象方法的迭代将会停止,后面的方法将不会被执行,怎么处理这个问题呢?
看下面代码:
Delegate[] del=getResult.GetInvocationList();
foreach (DGetResult _getResult in del)
{
try
{
_getResult(4,2);
}
catch(Exception)
{
Console.WriteLine("异常被引发了");
}
}
此种方法是,委托对象通过GetInvocationList()方法返回一个Delegate对象数组,然后遍历这个Delegate数组,进行自定义处理,这样,前面的方法出现异常了,委托对象还会迭代方法,后面的方法就不会因前面的异常而受阻了。
1.2 为什么要有委托
首先,委托是类型安全的,委托容易控制,效率高;另外大型应用程序中使用委托可以减少依赖性和层的耦合,为开发出更高性能的组件提供支持。
1.3 Lambda表达式
C#中有匿名方法,但是匿名方法写起来还是不怎么方便,所以C#3.0开始,出现了Lambda表达式,这种语法只能用超爽两个字来习惯,这是C#给他的程序员给开的小灶,C#的程序员们一定要为之感到庆幸。
Lambda表达式组成:(参数1,参数2..)=>{具体实现};
一切具有委托参数类型的地方,都可以使用Lambda表达式,匿名方法如果用Lambda表达式写那应该是非常爽的一件事情。
Lambda表达式的举例会在下面两个常用委托中进行。
1.4 Action委托和Func委托
我们在查阅MSDN帮助文档的时候,能够看见很多Action<T>和Func<T>的形式存在,以前没有见过这种结构的代码呢?它们到底是什么呢?
不要恐慌,他们都是委托,只不过他们更简单更常用而已。
1.4.1 Action委托
Action委托表示引用一个void返回类型的方法,参数可以自定义。
如:Action<int,string,bool>表示带三个参数返回void委托,我们可以用Lambda表达式简写委托的定义和调用:
Action<int, string> action = (a, b) =>
{
Console.WriteLine(a.GetType().ToString());
Console.WriteLine(b.GetType().ToString());
}; //Action委托的定义
action(1,"1"); //调用委托对象
程序输出:
System.Int32
System.String
1.4.2 Func委托
Func<T1,T2,T3>委托表示一个带有2个参数,返回T3类型的委托,即最后一个参数是返回类型,前面所有参数均是参数表,看下面代码。
Func<int,string,bool> function=(a,b)=>
{
Console.WriteLine(a.GetType().ToString());
Console.WriteLine(b.GetType().ToString());
return false;
};
function(1,"1");
程序输出:
System.Int32
System.String
委托这个知识点属于.Net高级技术,所以对于初学者来说理解和应用起来都有点难度,越是感觉生疏,就越是闭关练习,因为这是修仙成佛的必经之路。
委托总结:
最后,给大家推荐一本觉得可以推荐一千次一万次的书籍,这本书叫C#高级编程,书籍作者是美国的Christian Nagel,Bill Evjen和Jay Glynn等,中文版由李铭翻译,为什么推荐这本书呢?因为这本书几乎囊括了所有.Net知识点,讲解的也非常到位,现在出版到第八版,网上有第七版的中文版和第八版的英语版,看哪个版本看你的喜好了。