C# 委托、事件

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值