首页 > 其他 > 详细

C#事件与委托的区别

时间:2014-02-24 22:33:13      阅读:425      评论:0      收藏:0      [点我收藏+]

  1. 委托

事件是利用委托来定义的,因此先解释委托。委托是一个类,它与其他类如int,string等没有本质区别,int代表的是所有的整形,而string代表的是字符串,委托则代表的是一类方法,这类方法具有相同返回类型和相同参数。委托的定义:

bubuko.com,布布扣
  public delegate void CalculatorHandler(int x,int y);
bubuko.com,布布扣

 

从CalculatorHandler这个委托的定义可以看出,它反应的是一类方法,这类方法的返回类型是void,两个参数是(int x,int y),因此以后所有具有这样特征的方法都可以用这个委托来代替,现有以下这个方法:

bubuko.com,布布扣
     static void Add(int x, int y)
        {
           Console.WriteLine("x+y={0}",x+y);
        }
bubuko.com,布布扣

首先要将这个方法赋值给这个委托才可以使用,就如普通的类赋值一样,

CalculatorHandler calhandler = new CalculatorHandler(Add)

当然你也可以像给一个整形赋值一样,这样赋值:

CalculatorHandler calhander = Add;

当要调用这个方法的时候,你可以就像使用方法一样使用委托,

calhander(3,4);

委托也可以绑定多个方法,当调用这个委托时,会调用所有已经绑定了的方法,如现在还有这样的方法:

bubuko.com,布布扣
        static void Multiply(int x, int y)
        {
            Console.WriteLine("x*y={0}",x*y);
        }
bubuko.com,布布扣

只需在calhandler基础上多绑定个方法,具体语法:

calhander += Multiply;

这样当调用

calhander(3,4);

会同时调用Add和Multiply这两个方法,你也可以利用“-=”解绑方法:

calhander -= Multiply;

这样再次调用这个委托,则只会调用Add这个方法。

2. 事件

一说到事件总会有发布者(publisher)和订阅者(subscriber),发布者定义了一个事件,订阅者订阅了该事件(指的是当该事件触发时,订阅者做出什么样的反应,即利用相应的函数去处理)。该函数的定义与定义该事件的委托配套。代码如下:

bubuko.com,布布扣
public delegate void MessageEventHandler();
    class Publisher
    {
        public event MessageEventHandler MessageEvent;
        public void DoSomething()
        {
            Console.WriteLine("等待消息");
            Console.WriteLine("首长来啦!!!");
            OnMessageEvent();
        }
        public void OnMessageEvent()
        {
            if (MessageEvent != null)
            {
                MessageEvent();
            }
        }
    }
    class Subscriber
    {
        public Subscriber(Publisher p)
        {
            p.MessageEvent += Response;
        }

        public void Response()
        {
            Console.WriteLine("首场,辛苦了");
        }
}

    class Program
    {
        static void Main(string[] args)
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber(p);
            p.DoSomething();
            Console.ReadKey();
        }
    }
}
bubuko.com,布布扣

这就是事件的基本用法,但是事件与委托到底有什么区别呢,从上面的代码可以看出,事件是根据委托来定义的,

bubuko.com,布布扣
public event MessageEventHandler MessageEvent
bubuko.com,布布扣

其实它是利用委托来规定订阅者处理函数的类型(相同的返回类型和参数即为一类),然后可以方便在发布者自身的类中来触发订阅者的一些方法。

但是为什么要事件呢,要实现这些,我仅用委托也可以实现呀,如下代码:

bubuko.com,布布扣
 public delegate void MessageEventHandler();
    class Publisher
    {
        public MessageEventHandler MessageEvent;//为了方便,委托名与原来的事件名相同。
       // public event MessageEventHandler MessageEvent;
        public void DoSomething()
        {
            Console.WriteLine("等待消息");
            Console.WriteLine("首长来啦!!!");
            OnMessageEvent();
        }
        public void OnMessageEvent()
        {
            if (MessageEvent != null)
            {
                MessageEvent();
            }
        }
    }
    class Subscriber
    {
        public Subscriber(Publisher p)
        {
            p.MessageEvent += Response;
        }

        public void Response()
        {
            Console.WriteLine("首场,辛苦了");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber(p);
            p.DoSomething();
            Console.ReadKey();
        }
}
bubuko.com,布布扣

这样子也同样可以产生相同的结果。

但是当客户端如下调用呢?

bubuko.com,布布扣
 Publisher p = new Publisher();
 Subscriber s = new Subscriber(p);
 p.DoSomething();
 p.MessageEvent();
 Console.ReadKey();
bubuko.com,布布扣

客户端是不是能随意让发布者产生事件,因此我们可否将发布者的委托定义为private,因为只有发布者的内部才能触发事件嘛,其他人怎么可以?但是这样订阅者就无法订阅了,那我们是否可以增加绑定可解除的函数来订阅此委托呢?

bubuko.com,布布扣
public delegate void MessageEventHandler();
    class Publisher
    {
        private MessageEventHandler MessageEvent;
       // public event MessageEventHandler MessageEvent;
        public void DoSomething()
        {
            Console.WriteLine("等待消息");
            Console.WriteLine("首长来啦!!!");
            OnMessageEvent();
        }
        public void OnMessageEvent()
        {
            if (MessageEvent != null)
            {
                MessageEvent();
            }
        }
        public void Add_MessageEvent(MessageEventHandler m)
        {
            MessageEvent += m;               
        }
        public void Reomove_MessageEvent(MessageEventHandler m)
        {
            MessageEvent -= m;
        }
    }
    class Subscriber
    {
        public Subscriber(Publisher p)
        {
            //p.MessageEvent += Response;
            p.Add_MessageEvent(Response);
        }

        public void Response()
        {
            Console.WriteLine("首场,辛苦了");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber(p);
            p.DoSomething();           
            Console.ReadKey();
        }
    }
}
bubuko.com,布布扣

这样就可以实现与事件一样的功能,因此为了方便微软为我们提供了事件访问器,何为事件访问器?

bubuko.com,布布扣
public delegate void MessageEventHandler();
    class Publisher
    {
        private MessageEventHandler MessageEvent;
       // public event MessageEventHandler MessageEvent;

        public event MessageEventHandler TestEvent
        {
            add
            {
                lock (MessageEvent)
                {
                    MessageEvent += value;
                }
            }
            remove
            {
                lock (MessageEvent)
                {
                    MessageEvent -= value;
                }

            }
        }
        public void DoSomething()
        {
            Console.WriteLine("等待消息");
            Console.WriteLine("首长来啦!!!");
            OnMessageEvent();
        }
        public void OnMessageEvent()
        {
            if (MessageEvent != null)
            {
                MessageEvent();
            }
        }

    }
    class Subscriber
    {
        public Subscriber(Publisher p)
        {
            p.TestEvent += Response;
            
        }

        public void Response()
        {
            Console.WriteLine("首场,辛苦了");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber(p);
            p.DoSomething();           
            Console.ReadKey();
        }
}
bubuko.com,布布扣

以上的代码就是利用事件访问器来让委托绑定订阅者的方法,事件访问器中的add和remove能自动编译为+=和-=。

通过reflector,我们可以看到一个事件是如何定义的:

bubuko.com,布布扣

它是申明一个私有的委托:

bubuko.com,布布扣
private MessageEventHandler MessageEvent;
bubuko.com,布布扣

另外利用两个函数来绑定与解除订阅者的方法。

C#事件与委托的区别

原文:http://www.cnblogs.com/Celvin-Xu/p/3562506.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!