zoukankan      html  css  js  c++  java
  • .NET 中的event机制以及和delegate的区别

     
        使用.NET也有些日子了, 但对event这个东西一直没有去深入认识. 这两天因为想在DataGridView的cell里实现一个AutoComplete的功能, 趁机了解了一下, 下面贴上一点心得.

        Event机制其实是一个典型的Observer pattern: Publisher抛出一个事件, 所有订阅了该事件的Subscriber对此做出各自的响应. 
        简单看下这个过程:

        Publisher:

            public class Publisher
            
    {
                
    //Publisher exposes an event for subscribers.
                public event EventHandler OnPublish;

                
    public void InvokeMe(EventArgs e)
                
    {
                    
    //Publisher trigger this event.
                    if (OnPublish != null)
                        OnPublish(
    this, e);                
                }

            }


            Subscriber:

            public class Subscriber
            
    {
                
    private Publisher m_Pub;

                
    //Subscriber expose a property to hook up a publisher's event.
                public Publisher MyPublisher
                
    {
                    
    get return m_Pub; }
                    
    set 
                    

                        m_Pub 
    = value;
                        m_Pub.OnPublish 
    += PublishHandler;
                    }

                }


                
    //Subscriber's behavior to publisher's event.
                private void PublishHandler(object sender, EventArgs e)
                
    {
                    Console.WriteLine(
    string.Format("Subscriber response to {0}",sender.ToString()));
                }

            }


            跑一下:

            static void Main(string[] args)
            
    {
                Publisher publisher 
    = new Publisher();
                Subscriber subscriber 
    = new Subscriber();
                
    //Subscriber subscribe a publisher.
                subscriber.MyPublisher = publisher;
                
    //Trigger publisher's event.
                publisher.InvokeMe(new EventArgs());
                Console.ReadLine();
            }

       

        使用reflector 查看源代码, 发现CLR自动为Publisher类生成了一个EventHandler类型的成员:
        private EventHandler OnPublish;

       以及两个操作方法:

    public void add_OnPublish(EventHandler value)
    {
        
    this.OnPublish = (EventHandler) Delegate.Combine(this.OnPublish, value);
    }


    public void remove_OnPublish(EventHandler value)
    {
        
    this.OnPublish = (EventHandler) Delegate.Remove(this.OnPublish, value);
    }


        
        看起来OnPublish和普通的delegate对象使用上并没有什么区别.
    至此,有了一个疑问: 既然使用delegate就可以实现整套Event机制了, 那么event关键字的意义何在呢? 

        我觉得是为了代码可读性. 一个被event修饰的delegate类型更加醒目, 提示着这个delegate类型的用途. 另外编译器会为event关键字修饰的delegate类型自动生成成员变量, 使代码看起来更加简洁直观. 不知道还有没有什么历史原因, 暂且就先认为是这两条吧. 

        至此, 整个Event机制比较明了了, 简单说来, 就是subscriber把自己的函数地址赋给了一个特定的publisher的函数指针变量而已. 而在.NET Framework中, 这些地址就是一个个delegate对象了. 为了简化问题, 示例没有使用自定义的EventHandler, 关于自定义EventHandler可以参考 How to: Publish Events that Conform to .NET Framework Guidelines 这篇文章. 

       



    后记:今天查阅了一下 CLR via C#. 事实上, CLR对event关键字的实现有两点好处是直接使用delegate所没有的:
    第一, 注意到生成的OnPublish变量是private的, 外界对它的访问只能通过add_OnPublish和remove_OnPublish这两个方法(+=和-=两个操作符最终会被编译成对这两个方法的调用). 显然, 这样对OnPublish的封装更好, 如果直接暴露一个public的delegate, 则有可能因为一个subscriber误操作使整个委托链表被清空, 影响到其他的subscriber. 最重要的是,正如楼下“吉祥如意”所说,这样保证了event只能由类的内部触发,外界只能对event成员执行增减监听方法的操作,而不能直接触发event,这样的行为模式符合了event的设计目的。另外有一点要注意的是,因为 add_OnPublish和remove_OnPublish这两个方法是public的,所以类本身也可以为event添加处理方法,这点和“吉祥如意”所说的不同。

    第二, 注意到add_OnPublish和remove_OnPublish都带有[MethodImpl(MethodImplOptions.Synchronized)]属性, 表明它们是线程安全的, 多个subscriber不能同时访问这两个方法.


    我想,这两点才是使用event关键字的优势所在吧。



  • 相关阅读:
    Vijos P1448 校门外的树【多解,线段树,树状数组,括号序列法+暴力优化】
    Vijos P1785 同学排序【模拟】
    Vijos P1784 数字统计【模拟】
    Vijos P1497 立体图【模拟】
    将你的wordpress博客添加到百度个性首页
    改变wordpress图片上传后的压缩质量
    优化dedecms设置文章url自定义规则
    dedecms首页调用随机文章全自动时时更新
    怎样在wordpress后台显示日志 ID
    sql批量修改wordpress文章发布时间
  • 原文地址:https://www.cnblogs.com/k330/p/1067565.html
Copyright © 2011-2022 走看看