c#用自定义参数继承事件

本文关键字:继承 事件 参数 自定义 | 更新日期: 2023-09-27 18:07:36

我试图用自定义参数在接口中指定事件。我需要事件参数是一个对象。我已经尽可能地精简了下面的代码。我目前得到以下错误:

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;
    }
}

c#用自定义参数继承事件

这段代码相当混乱,但我相信你得到异常的原因是因为你锁定了一个null -引用。

当你这样做的时候:

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

编译器实际上使用私有字段来支持ChangeEvent事件(参见类似字段的事件)。请注意,这个字段的初始值是null(它没有被显式地分配一个初始值,比如通过字段初始化器)。

现在,当有人第一次订阅"包装"事件(someObject.ChangeEvent += ...)时,您的自定义 add访问器被调用,导致尝试获取由该字段引用的对象上的锁(锁实际上需要在称为"同步块"的对象头中的一些数据)。当然,不存在这样的对象,而正是这个对象导致了锁的"bang"。

至于奇怪的obj参数,它来自Monitor.TryEnter(object obj, ref bool lockTaken),这是c#锁语句编译成的(以前版本的c#针对不同的方法)。

老实说,我强烈考虑重新设计这段代码。

编辑:澄清了换行事件的使用