2011-09-06 23 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