C# 设置事件处理程序时使用空方法是一种不好的做法吗
我有一个包含许多类的类库,在每个类中我都会引发一些事件 每个事件都有自己的事件参数集,因此我将它们作为自动属性存储在继承自C# 设置事件处理程序时使用空方法是一种不好的做法吗,c#,events,C#,Events,我有一个包含许多类的类库,在每个类中我都会引发一些事件 每个事件都有自己的事件参数集,因此我将它们作为自动属性存储在继承自EventArgs的类中。然后,我可以通过调用Invoke并传入我的EventArgs继承类的新实例来引发相关事件。这就是我的意思: using System; //My Class Library namespace MyClassLibrary { //A class public class MyClass { //My eve
EventArgs
的类中。然后,我可以通过调用Invoke
并传入我的EventArgs
继承类的新实例来引发相关事件。这就是我的意思:
using System;
//My Class Library
namespace MyClassLibrary
{
//A class
public class MyClass
{
//My event is a field
public event EventHandler<MyEventHandler> myEvent;
//I raise my event in this method
public void InvokeMyEvent()
{
//Do some stuff
//I raise my event here
myEvent.Invoke(this, new MyEventHandler("The quick brown fox jumps over the lazy dog"));
//Do some more stuff
}
}
//An event handler, containing some interesting data about the event
public class MyEventHandler : EventArgs
{
//Some interesting data as an automatic property
public string MyInterestingData { get; private set; }
//I assign the value of my intersting data in my constructor
public MyEventHandler(string FooBar)
{
MyInterestingData = FooBar;
}
}
}
这一切编译都很好,但类库的重点肯定是要有一个可重用代码库,这当然是本文的意图。因此,我想将我的类库添加到许多项目中。在其中一些项目中,my有必要订阅myEvent
,在其他项目中则不会,但我仍然希望在这些项目中使用该类的其他功能,并且在将来可以选择订阅myEvent
但是,如果我在未订阅myEvent
的项目中使用类库,则每当引发myEvent
时,都会出现运行时错误
我在MyClass
的构造函数中订阅了myEvent
,并使用了如下空方法来解决这个问题:
public MyClass()
{
myEvent += new EventHandler<MyEventHandler>(MyClass_myEvent);
}
void MyClass_myEvent(object sender, MyEventHandler e)
{
}
publicmyclass()
{
myEvent+=新事件处理程序(MyClass_myEvent);
}
void MyClass_myEvent(对象发送方,MyEventHandler e)
{
}
这意味着我可以将我的类库添加到任何项目中,实例化MyClass
并使用它提供的其他功能,如果需要,可以订阅myEvent
,如果不需要,则忽略myEvent
问题是我的类中有一个空方法。想象一下这个场景,但是大约有30个事件,因此有30个空方法
几个问题
谢谢通常的做法是在引发事件之前检查
null
。就你而言:
if (myEvent != null)
myEvent.Invoke(this, new MyEventHandler("The quick brown fox jumps over the lazy dog"));
通常的做法是在引发事件之前检查
null
。就你而言:
if (myEvent != null)
myEvent.Invoke(this, new MyEventHandler("The quick brown fox jumps over the lazy dog"));
这通常是您看到以下事件模式的原因:
private void OnMyEvent(object sender, MyEventArgs args)
{
var ev = myEvent;
if (ev != null)
ev(sender, args);
}
OnMyEvent(this, new MyEventArgs("The quick brown fox jumps over the lazy dog"));
如果没有订阅服务器,则事件将为null。此代码获取本地副本,以确保检查点的事件不涉及竞争条件。然后调用该副本。即使这样可以防止一种形式的竞争条件,原始订户列表仍可能发生更改,而这些更改在副本中不可见,因此它不是完全线程安全的
老实说,我从来没有考虑过,甚至没有见过你这样做。我说最好还是使用空检查,而不是空方法订户,人们期望使用前者,而不是后者
此外,空方法路由会消耗内存/对象,而空路由只会消耗一次检查
顺便说一句,
MyEventHandler
arguments类通常被称为类似于MyEventArgs
的类,这通常就是您看到以下事件模式的原因:
private void OnMyEvent(object sender, MyEventArgs args)
{
var ev = myEvent;
if (ev != null)
ev(sender, args);
}
OnMyEvent(this, new MyEventArgs("The quick brown fox jumps over the lazy dog"));
如果没有订阅服务器,则事件将为null。此代码获取本地副本,以确保检查点的事件不涉及竞争条件。然后调用该副本。即使这样可以防止一种形式的竞争条件,原始订户列表仍可能发生更改,而这些更改在副本中不可见,因此它不是完全线程安全的
老实说,我从来没有考虑过,甚至没有见过你这样做。我说最好还是使用空检查,而不是空方法订户,人们期望使用前者,而不是后者
此外,空方法路由会消耗内存/对象,而空路由只会消耗一次检查
顺便说一句,
MyEventHandler
arguments类通常被称为类似于MyEventArgs
处理此问题的标准方法是不引发没有订阅者的事件:
var handler = myEvent;
if (handler != null)
{
handler(sender, new MyEventArgs());
}
如果在多线程场景中,单个订阅服务器在
null
检查和调用之间取消订阅,则分配给中间handler
变量可避免获得异常。处理此问题的规范方法是不引发没有订阅服务器的事件:
var handler = myEvent;
if (handler != null)
{
handler(sender, new MyEventArgs());
}
如果在多线程场景中,单个订户在
null
检查和调用之间取消订阅,则分配给中间handler
变量可避免获得异常。事件MyEvent的典型实现如下所示:
protected virtual void OnMyEvent(MyEventArgs eventArgs) {
var handler = MyEvent;
if (handler != null) {
handler(this, eventArgs);
}
}
然后,无论何时您想要触发事件,都可以调用OnMyEvent而不是MyEvent。事件MyEvent的典型实现如下所示:
protected virtual void OnMyEvent(MyEventArgs eventArgs) {
var handler = MyEvent;
if (handler != null) {
handler(this, eventArgs);
}
}
然后,无论何时您想要触发事件,都可以调用OnMyEvent而不是MyEvent。使用空处理程序初始化事件没有什么错。我总是这样做。如果要调用该事件数千次,它可能会比您想要的慢(测试、测量、决定) 设置空处理程序时,您不必太罗嗦,您可以这样做:
myEvent = (sender, args) => { };
并避免创建方法…使用空处理程序初始化事件没有错。我总是这样做。如果要调用该事件数千次,它可能会比您想要的慢(测试、测量、决定) 设置空处理程序时,您不必太罗嗦,您可以这样做:
myEvent = (sender, args) => { };
避免创建方法…我希望我能看到你的意思。我认为,你可以把自己的工作留给那些空洞的方法。只需按以下方式调用事件:
//I raise my event in this method
public void InvokeMyEvent()
{
//Do some stuff
//Check if there are subscribers!!
if (myEvent != null)
myEvent.Invoke(this, new MyEventHandler("The quick brown fox jumps over the lazy dog"));
//Do some more stuff
}
我希望我明白你的意思。我认为,你可以把自己的工作留给那些空洞的方法。