use*_*443 3 c# events interface
我试图在自定义参数的接口中指定一个事件.我需要将event参数作为一个对象.我试图尽可能地删除以下代码.我目前收到以下错误.
ArgumentNullException: Argument cannot be null.
Parameter name: obj
LittleObject.IObject.add_ChangeEvent (System.EventHandler`1 value)
(at LittleObject.cs line : [where the comment is])
Run Code Online (Sandbox Code Playgroud)
码
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;
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码非常混乱,但我相信你得到异常的原因是因为你锁定了一个null引用.
当你这样做时:
add
{
lock (ChangeEvent) { ... }
}
Run Code Online (Sandbox Code Playgroud)
编译器实际上使用支持事件的私有字段ChangeEvent(请参阅字段类事件).请注意,此字段的初始值为null(未明确分配初始值,例如通过字段初始化程序).
现在有人第一次订阅"wrap"事件(someObject.ChangeEvent += ...)时,会调用自定义 add访问者,导致尝试锁定该字段引用的对象(该锁实际上需要在对象头中调用一些数据) '同步块').当然,没有这样的对象,这就是锁定爆炸的原因.
至于奇怪的obj参数,就是那个Monitor.TryEnter(object obj, ref bool lockTaken),这是C#lock语句编译成的(C#的早期版本针对不同的方法).
老实说,我会强烈考虑重新设计这整段代码.
编辑:澄清了包装事件的使用.