参考文档:分分钟用上C#中的委托和事件 - 雾中人 - 博客园 (cnblogs.com) 这里用了一个摔杯起兵的例子讲述规则
c#委托_百度百科 (baidu.com) 委托的百科 讲解得很详细
简单地来说,类似于int ; double这样 委托就是用来声明方法的一种类,它的实例也类似于函数指针。通过委托,方法内可以灵活调用其他方法,实现代码的简洁,防止多处改动。
委托适用于什么情况呢?一个是如下所示的代码设计模式,每次不需要改动主函数;或者是已经确定了所需的方法,但是不能确定实际的触发时间。以上面的摔杯起兵为例,两队士兵做好了准备,看到摔杯就动手,但他们不确定具体什么时候动手。委托与事件配合,可以实现实时响应的效果。
首先是设计模式:
public enum Language { English, Chinese } public void GreetPeople(string name, Language lang) { //做某些额外的事情,比如初始化之类,此处略 switch(lang) { case Language.English: EnglishGreeting(name); break; case Language.Chinese: ChineseGreeting(name); break;
case 其他语言.... } }
这里是百科的例子,一个问候函数,遇到中国人说你好,遇到英国人说hello。每一次有新的语言出现时,我们都要反复修改这个函数,比较麻烦,所以我们用委托,去掉switch,把要用的方法也传进来:
public delegate void GreetingDelegate(string name); class Program { private static void EnglishGreeting(string name) { Console.WriteLine("Morning, " + name); } private static void ChineseGreeting(string name) { Console.WriteLine("早上好, " + name); } //此方法接受一个GreetingDelegate类型的参数,该参数是一个方法,它的返回值为空,参数为string,上面两个方法就可以套进来 private static void GreetPeople(string name, GreetingDelegate MakeGreeting) { MakeGreeting(name); } void Main() { GreetPeople("Jimmy Zhang", EnglishGreeting); GreetPeople("张子阳", ChineseGreeting); Console.ReadKey(); } }
通过这个设计,GreetPeople这个方法就不需要反复改动,每次有新方法时,只要把方法名作为参数,传入GreetPeople即可。就像是C中的函数指针
委托的声明方式和方法比较类似:
public delegate void xxxEventHandler(如果需要参数) //命名时,推荐用 要添加的方法名+Handler 来声明委托,方便查找
在此时,就声明 了一个名为xxxEventHandler的委托。
除此之外,委托还有一个特点,就是它和要绑定的方法可以是多对一的方法。以上面的摔杯起兵为例,配合事件来使用:
public event RaiseEventHandler RaiseEvent;//举杯事件 public event FallEventHandler FallEvent; //摔杯事件
事件的存在是为了封装委托,防止不必要的权限被放出去。与直接声明一个委托变量相比就多了一个event。它就相当于一个对象。它拥有注册和解绑函数的功能。
在B中实例化出一个事件时,可以通过+=符号来绑定多个方法,一旦该事件被收听到,绑定的方法都会执行,执行的顺序就是绑定时的顺序;同样,-=符号可以去掉某个绑定的方法。与委托的实例相比,事件不允许再使用=。代码中使用委托,并不一定非要匹配事件一块用,但按照代码的设计原则推荐一块用。
委托的一些注意事项:
1.需要先初始化后才能使用+=号,否则第一次需要使用等号,不使用就会提示“使用了未赋值的局部变量”。
2.不能继续派生其他类
3.在使用委托前必须先检查是否为空,不为空才能使用。
4.可以直接封装静态方法,参数是类名.方法名;也可以封装实例方法,参数是实例名.方法名。