在使用delegate时,使用event 与不使用的区别

转自:http://www.cnblogs.com/shensr/archive/2005/11/24/283653.html


首先说明,event其实也是一种delegate,为了区分,我们称一般的delegate为“plain delegate”。

using System;

namespace EventAndDelegate
{
    public delegate void TestDelegate(string s);

    public interface ITest {
        // 【区别】 1. event可以用在interface中,而plain delegate不可以(因为它是field)
        event TestDelegate TestE;   // Passed
        TestDelegate TestD;         // Error: Interfaces cannot contain fields
    }

    public class Parent {
        public event TestDelegate TestE;
        public TestDelegate TestD;

        protected void RaiseTestE(string s)
        {
            TestE(s);   // The event 'EventAndDelegate.Parent.TestE' can only
                        // be used from within the type 'EventAndDelegate.Parent'
        }
    }

    public class Child : Parent {
        void ChildFunc()
        {
            // 【区别】 2. event不允许在声明它的class之外(即使是子类)被调用(除此之外只能用于+=或-=),而plain delegate则允许
            TestD("OK");        // Passed
            TestE("Failure");   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                //        the left hand side of += or -= (except when used from within
                                //        the type 'EventAndDelegate.Parent')

            // 【补充】 在子类中要触发父类声明的event,通常的做法是在父类中声明一个protected的Raisexxx方法供子类调用
            RaiseTestE("OK");   // The class 'EventAndDelegate.Child' can only call the
                                // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                // 'EventAndDelegate.Parent.TestE'

            // 【区别】 同2#
            object o1 = TestD.Target;
            object o2 = TestE.Target;   // The class 'EventAndDelegate.Child' can only call the
                                        // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                        // 'EventAndDelegate.Parent.TestE'

            // 【区别】 同2#
            TestD.DynamicInvoke("OK");
            TestE.DynamicInvoke("OK");   // The class 'EventAndDelegate.Child' can only call the
                                        // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
                                        // 'EventAndDelegate.Parent.TestE'
        }
    }

    class Other
    {
        static void Main(string[] args)
        {
            Parent p = new Parent();

            p.TestD += new TestDelegate(p_Test1);   // Passed
            p.TestE += new TestDelegate(p_Test1);   // Passed

            // 【区别】 3. event不允许使用赋值运算符,而plain delegate则允许。
            //             注意,对plain delegate,使用赋值运算符意味着进行了一次替换操作!
            p.TestD = new TestDelegate(p_Test2);   // Passed
            p.TestE = new TestDelegate(p_Test2);   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                                   //        the left hand side of += or -= (except when used from within
                                                   //        the type 'EventAndDelegate.Parent')

            // 【区别】 同2#
            p.TestD("OK");      // Passed
            p.TestE("Failure"); // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
                                //        the left hand side of += or -= (except when used from within
                                //        the type 'EventAndDelegate.Parent')
        }

        static void p_Test1(string s)
        {
            Console.WriteLine("p_Test1: " + s);
        }

        static void p_Test2(string s)
        {
            Console.WriteLine("p_Test2: " + s);
        }
    }
}

分析:
plain delegate与event的关系类似于field与Property(实事上前者就是field,或者我们可以把event看成是一种特殊的Property)
正是由于1#,在使用上,plain delegate几乎没有任何限制,而event则有严格的限制(只能用在+=和-=的左边)


结论:
event更面向对象一些。
当我们需要灵活时,直接使用plain delegate;反之,需要严格的控制时,使用event。
由于event不能使用赋值运算符,因此有时我们要求一个事件在任何时刻只能有一个响应方法时,我们使用plain delegate更为方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值