2011-09-06 49 views
3

我試圖用自定義參數在接口中指定一個事件。我需要事件參數是一個對象。我試圖儘可能去除下面的代碼。我目前得到以下錯誤。C#使用自定義參數的繼承事件

ArgumentNullException: Argument cannot be null. 
Parameter name: obj 
LittleObject.IObject.add_ChangeEvent (System.EventHandler`1 value) 
(at LittleObject.cs line : [where the comment is]) 

代碼

public class ChangeEventArgs : EventArgs { 
    public ChangeEventArgs(SomeClass c){ someClass = c;} 
    public SomeClass someClass; 
} 


public interface IObject { 
    void OnChangeEvent(ChangeEventArgs e); 
    event EventHandler<ChangeEventArgs> ChangeEvent; 
} 


public class LittleObject : IObject{  

    public event EventHandler<ChangeEventArgs> ChangeEvent; 

    public fireEvent(){ 
     OnChangeEvent(new ChangeEventArgs(new SomeClass())); 
    } 

    event EventHandler<ChangeEventArgs> IObject.ChangeEvent{ 
     add{        // error here 
      lock (ChangeEvent) { 
       ChangeEvent += value; 
      } 
     } 
     remove{ 
      lock (ChangeEvent){ 
       ChangeEvent -= value; 
      } 
     } 
    } 

    public void OnChangeEvent(ChangeEventArgs e){ 
     if(ChangeEvent != null) { 
      ChangeEvent(this, e); 
     } 
    } 
} 


public class Main { 

    IObject currentObject; 

    void init(){ 
     currentObject = new IObject(); 
     currentObject.ChangeEvent += new EventHandler<ChangeEventArgs>(OnChangeEvent); 
    } 

    void doStuff(){ 
     currentObject.fireEvent(); 
    } 

    public void OnChangeEvent(object sender, ChangeEventArgs e) { 
     SomeClass someClass = e.someClass; 
    } 
} 
+0

代碼編譯?你正試圖實例化一個接口'new IObject(); ' – Chandu

+0

加:鎖是昂貴的 - 你真的需要它嗎?通過將FireEvent方法內部的ChangeEvent賦值爲局部變量,有一種簡單的技術可以避免鎖定。 –

回答

7

此代碼是相當混亂,但我相信你得到異常的原因是因爲你在null -reference鎖定。

當你這樣做:

add 
{ 
    lock (ChangeEvent) { ... } 
} 

編譯器實際上是使用私有來頭ChangeEvent事件(見field-like event)。請注意,此字段的初始值爲null(它沒有明確指定初始值,例如通過字段初始值設定)。

現在第一次有人訂閱了「包裝」事件(someObject.ChangeEvent += ...),您定製add訪問被調用,從而試圖通過實地採取所指的對象上的鎖(鎖實際上在對象頭中需要一些稱爲'sync-block'的數據)。當然,沒有這樣的對象,這是什麼讓鎖一觸即發。

至於奇怪obj參數,這是從Monitor.TryEnter(object obj, ref bool lockTaken)的一個,這是一個C#lock語句編譯成(C#的早期版本中針對不同的方法)。老實說,我會強烈地考慮重新設計這整段代碼。

編輯:澄清使用包裝事件。

+0

現貨,歡呼聲。 – user346443