2011-04-13 72 views
4

我有這樣的程序:C#事件繼承

class One 
    { 
     public delegate void del(object o); 
     public event del SomethingChanged; 

     int x; 
     public int X 
     { 
      get { return x; } 
      set { x = value; OnSomethingChanged(this); } 
     } 

     protected void OnSomethingChanged(object o) 
     { 
      if (SomethingChanged != null) 
       SomethingChanged(o); 
     } 
    } 

    class Two: One 
    { 
     public void ChangeSomething() 
     { 
      //if (SomethingChanged != null) 
      // SomethingChanged(this); 
      OnSomethingChanged(this); 
     } 
    } 

    static void Main(string[] args) 
    { 
     One one = new One(); 
     Console.WriteLine(one.X); 
     one.SomethingChanged += new One.del(one_SomethingChanged); 
     one.X = 5; 
    } 

    static void one_SomethingChanged(object o) 
    { 
     Console.WriteLine(((One)o).X); 
    } 

有2類 - 一,二,二就是一個後代。在第一類(SomethingChanged)中聲明瞭事件,它由第一類和第二類觸發。但看看Two.ChangeSomething - 它通過調用基類的方法來引發事件。但是,如果我嘗試使用原始代碼來調用事件像

 
if (SomethingChanged != null) 
    SomethingChanged(this); 

我收到編譯器錯誤說

 
The event 'One.SomethingChanged' can only appear on the left hand side of += or -= (except when used from within the type 'eventstest.Program.One') 

所以我只是好奇,爲什麼我不能在課堂上使用「原始」碼兩個引發事件,但當我調用一個相應的函數事件時被引發?

[編輯] 發現了一些澄清一下: C#: Raising an inherited event

回答

1

代碼

if (SomethingChanged != null) 
    SomethingChanged(this); 

(其具有競爭條件,順便)意味着調用SomethingChangedDelegate.GetInvocationList。自動實現的事件不允許你這樣做,除非你在班級中定義事件。

如果您手動實施事件並提供protected訪問委託字段,則可以這樣做支持事件。

0

用途:

this.SomethingChanged += new One.del(one_SomethingChanged); 
6

當你聲明使用C#中的「事件」的關鍵字,生成的IL實際上包含兩個對應的元素的事件:一個私人代表場,並用相同的可見性的事件訪問宣佈的事件。事件訪問器不能用於觸發事件。它僅用於訂閱和取消訂閱通知。您的SomethingChanged(this)代碼正在使用專用字段來調用委託,並且該專用字段在類外部不可用。

+1

剛剛發佈一個鏈接到一個老喬恩Skeet的答案,幾乎說這個(http://stackoverflow.com/questions/253757/why-events-cant-be-used-in-the-same在派生類中,如在基類中#253803)+1 – RobV 2011-04-13 11:50:06