gpt4 book ai didi

c# - 使用扩展方法引发 C# 事件 - 这不好吗?

转载 作者:IT王子 更新时间:2023-10-29 03:50:04 25 4
gpt4 key购买 nike

我们都熟悉 C# 事件声明的可怕之处。为确保线程安全,the standard is to write something like this :

public event EventHandler SomethingHappened;
protected virtual void OnSomethingHappened(EventArgs e)
{
var handler = SomethingHappened;
if (handler != null)
handler(this, e);
}

最近在此板上的其他一些问题(我现在找不到)中,有人指出在这种情况下可以很好地使用扩展方法。这是一种方法:

static public class EventExtensions
{
static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
{
var handler = @event;
if (handler != null)
handler(sender, e);
}
static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
where T : EventArgs
{
var handler = @event;
if (handler != null)
handler(sender, e);
}
}

有了这些扩展方法,您只需声明和引发一个事件,就像这样:

public event EventHandler SomethingHappened;

void SomeMethod()
{
this.SomethingHappened.RaiseEvent(this, EventArgs.Empty);
}

我的问题:这是个好主意吗?我们是否因为没有标准的 On 方法而遗漏了什么? (我注意到的一件事是它不适用于具有显式添加/删除代码的事件。)

最佳答案

它仍然适用于具有显式添加/删除的事件 - 您只需要使用委托(delegate)变量(或者您已经存储了委托(delegate))而不是事件名称。

但是,有一种更简单的方法可以使其成为线程安全的 - 使用无操作处理程序对其进行初始化:

public event EventHandler SomethingHappened = delegate {};

调用额外委托(delegate)对性能的影响可以忽略不计,而且它确实使代码更简单。

顺便说一句,在您的扩展方法中您不需要额外的局部变量——您可以这样做:

static public void RaiseEvent(this EventHandler @event, object sender, EventArgs e)
{
if (@event != null)
@event(sender, e);
}

static public void RaiseEvent<T>(this EventHandler<T> @event, object sender, T e)
where T : EventArgs
{
if (@event != null)
@event(sender, e);
}

就我个人而言,我不会使用关键字作为参数名称,但它根本不会真正改变调用方,所以随心所欲:)

编辑:至于“OnXXX”方法:你打算派生你的类吗?在我看来,大多数类应该是密封的。如果您这样做,您是否希望那些派生类能够引发该事件?如果这些问题中的任何一个的答案是“否”,那么请不要打扰。如果两者的答案都是"is",那么就做 :)

关于c# - 使用扩展方法引发 C# 事件 - 这不好吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/231525/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com