1. 程式人生 > >c# delegate ,event

c# delegate ,event

賦值 () ear get alt 運算符 app all fun

首先說明,event其實也是一種delegate,為了區分,我們稱一般的delegate為“plain delegate”。

寫代碼的過程中,經常會在delegate和event之間進行選擇,以前也沒仔細思考選擇的原因,今天終於忍不住花了半天時間仔細琢磨了一下……好了,直接拿代碼說話吧:

技術分享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);
技術分享 }
技術分享 }
技術分享}
技術分享


分析:

  1. plain delegate與event的關系類似於field與Property(實事上前者就是field,或者我們可以把event看成是一種特殊的Property)
  2. 正是由於1#,在使用上,plain delegate幾乎沒有任何限制,而event則有嚴格的限制(只能用在+=和-=的左邊)

結論

    1. event更面向對象一些。
    2. 當我們需要靈活時,直接使用plain delegate;反之,需要嚴格的控制時,使用event。
    3. 由於event不能使用賦值運算符,因此有時我們要求一個事件在任何時刻只能有一個響應方法時,我們使用plain delegate更為方便。

c# delegate ,event