delegate vs. event(转自LTP.NET知识库)

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

写代码的过程中,经常会在delegate和event之间进行选择,以前也没仔细思考选择的原因,今天终于忍不住花了半天时间仔细琢磨了一下……好了,直接拿代码说话吧:
 1using System;
 2
 3namespace EventAndDelegate
 4{
 5    public delegate void TestDelegate(string s);
 6
 7    public interface ITest {
 8        // 【区别】 1. event可以用在interface中,而plain delegate不可以(因为它是field)
 9        event TestDelegate TestE;   // Passed
10        TestDelegate TestD;         // Error: Interfaces cannot contain fields
11    }

12
13    public class Parent {
14        public event TestDelegate TestE;
15        public TestDelegate TestD;
16
17        protected void RaiseTestE(string s)
18        {
19            TestE(s);   // The event 'EventAndDelegate.Parent.TestE' can only
20                        // be used from within the type 'EventAndDelegate.Parent'
21        }

22    }

23
24    public class Child : Parent {
25        void ChildFunc()
26        {
27            // 【区别】 2. event不允许在声明它的class之外(即使是子类)被调用(除此之外只能用于+=或-=),而plain delegate则允许
28            TestD("OK");        // Passed
29            TestE("Failure");   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
30                                //        the left hand side of += or -= (except when used from within
31                                //        the type 'EventAndDelegate.Parent')
32
33            // 【补充】 在子类中要触发父类声明的event,通常的做法是在父类中声明一个protected的Raisexxx方法供子类调用
34            RaiseTestE("OK");   // The class 'EventAndDelegate.Child' can only call the
35                                // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
36                                // 'EventAndDelegate.Parent.TestE'
37
38            // 【区别】 同2#
39            object o1 = TestD.Target;
40            object o2 = TestE.Target;   // The class 'EventAndDelegate.Child' can only call the
41                                        // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
42                                        // 'EventAndDelegate.Parent.TestE'
43
44            // 【区别】 同2#
45            TestD.DynamicInvoke("OK");
46            TestE.DynamicInvoke("OK");   // The class 'EventAndDelegate.Child' can only call the
47                                        // 'EventAndDelegate.ParentRaiseTestE' method to raise the event
48                                        // 'EventAndDelegate.Parent.TestE'
49        }

50    }

51
52    class Other
53    {
54        static void Main(string[] args)
55        {
56            Parent p = new Parent();
57
58            p.TestD += new TestDelegate(p_Test1);   // Passed
59            p.TestE += new TestDelegate(p_Test1);   // Passed
60
61            // 【区别】 3. event不允许使用赋值运算符,而plain delegate则允许。
62            //             注意,对plain delegate,使用赋值运算符意味着进行了一次替换操作!
63            p.TestD = new TestDelegate(p_Test2);   // Passed
64            p.TestE = new TestDelegate(p_Test2);   // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
65                                                   //        the left hand side of += or -= (except when used from within
66                                                   //        the type 'EventAndDelegate.Parent')
67
68            // 【区别】 同2#
69            p.TestD("OK");      // Passed
70            p.TestE("Failure"); // Error: The event 'EventAndDelegate.Parent.TestE' can only appear on
71                                //        the left hand side of += or -= (except when used from within
72                                //        the type 'EventAndDelegate.Parent')
73        }

74
75        static void p_Test1(string s)
76        {
77            Console.WriteLine("p_Test1: " + s);
78        }

79
80        static void p_Test2(string s)
81        {
82            Console.WriteLine("p_Test2: " + s);
83        }

84    }

85}

86

分析:

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

结论

  1. event更面向对象一些。
  2. 当我们需要灵活时,直接使用plain delegate;反之,需要严格的控制时,使用event。
  3. 由于event不能使用赋值运算符,因此有时我们要求一个事件在任何时刻只能有一个响应方法时,我们使用plain delegate更为方便。
  4. ……(大家补充)
posted @ 2007-08-18 08:34  LanceZhang  阅读(1037)  评论(0)    收藏  举报