C# 委托、事件

来源:互联网 发布:审计软件 编辑:程序博客网 时间:2024/06/06 00:26

C#的Delegate委托可以把方法当做参数传递,方便我们回调方法,它的用处很多,为我们编程提供了很大的便利。而Event又是委托的特殊形式。

委托Delegate

public delegate void GreetingDelegate(string name);
delegate 是委托的关键字,GreetingDelegate是一个委托类名,在编译后,它会由编译器生成委托类
public sealed class GreetingDelegate:Syste.MulticastDelegate{public GreetingDelegate(object @object, IntPtr method);public virtual IAsyncResult BeginInvoke(string name, AsyncCallback callback, object @object);public virtual void EndInvoke(IAsyncResult result);public virtual void Invoke(string name);}

(BeginInvoke和EndInvoke,是对委托异步回调的支持,关于异步回调,会在后面文章中涉及。)

方法定义,此方法只要传入参数和返回类型与委托定义的一样,就可以赋值给委托

public void EnglishGreeting(string name){}
首先委托类可以像参数一样传递在方法,属性中,如下:

public void GreetPeople(string name, GreetingDelegate MakeGreeting){   MakeGreeting(name);}
然后可以按下面的方式调用此方法:
GreetPeople("Jimmy Zhang", EnglishGreeting); //这代码看着有点奇怪吧?直接把方法作为了参数传递

委托类是需要实例化的,其实上面的方法内部已经帮你实例化了。它的实例化过程如下:

GreetingDelegate delegate1;delegate1 = EnglishGreeting;// 以赋值的方式实例化GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);//以构造方法方式实例化委托可以通过赋值方式实例化,也可以通过构造方式实例化,GreetPeople("Jimmy Zhang", EnglishGreeting)这里是通过赋值的方式实例化的

可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。

delegate1 = EnglishGreeting; // 先给委托类型的变量赋值delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法delegate1 -= ChineseGreeting; //当然也可以去掉一个委托方法

Event 事件

public event GreetingDelegate MakeGreet;

定义中多了event关键字,GreetingDelegate是上面定义的委托名。它封装了委托类型的变量,使得在类的内部,不管你声明它是public还是protected,它总是private的。在类的内部,可以直接调用它。在类的外部,只能使用+=或-=为它注册事件的执行方法,不能调用它去执行,这个是类的封装,只能由内部去触发事件(但是delegate是可以在外部直接调用,不需要封装方法的)。

委托事件

按照.Net Framework的编码规范:委托事件的名称都应该以EventHandler结束。 委托事件的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型,一个 EventArgs类型(或继承自EventArgs)。 事件的命名为 委托去掉 EventHandler之后剩余的部分。 继承自EventArgs的类型应该以EventArgs结尾。

定义委托事件的代码如下:

public delegate void ShowMessageEventHandler(Object sender, MessageEventArgs e); sender参数可以传递是谁触发的,e参数可以自定义一些需要的信息public event ShowMessageEventHandler ShowMessage; // 命名规范,一般以EventHandler结尾。定义eventargs
public class MessageEventArgs : EventArgs{//内部可以定义自己想要的信息}//注册的方法,方法签名必须与定义的委托的方法的签名相同void EventTest_ShowMessage(object sender, MessageEventArgs e){   Console.WriteLine("you have triggered ShowMessage event");}

注册事件

ShowMessage += EventTest_ShowMessage;

注册的时间可以是new ShowMessageEventHandler(EventTest_ShowMessage),也可以是+=,也可以用-=移出注册的事件

触发事件

ShowMessage(this, new MessageEventArgs());//如果在定义此事件的内部类,可以用这种方式直接触发。

在类的外部想调用ShowMessage,需要封装成一个方法,虽然是public的,但因为有event关键字,所以是无法编译通过的。如   public void TriggerEvent()        {            if (ShowMessage != null) {                ShowMessage(this, new MessageEventArgs("event is from trigger"));            }        }经过测试,对于event事件,定义时也可以是如下的这种形式        public delegate void NoParamEventHandler();        public event NoParamEventHandler NoParam;                       public void NoParamMethod()        {            Console.WriteLine("you have triggered NoParam event");        }注册           NoParam += NoParamMethod;触发NoParam();所以对于event与delegate的区别,<pre name="code" class="html">我的理解是虽然可以类似delegate一样使用,但事件是具有特殊含义的,专门用来处理事件模型,但是最好还是按照clr的编码规范来定义和使用,这样方便大家对代码的阅读和理解。顺便讲一下Func和Action,这2个是已经为我们定义好了的委托,方便让我们使用,我们不需要自己定义委托,直接可以用Func<T,TResult>和Action<T>,把签名一样的方法赋值给它们。

0 0