用扩展方法提高C#事件 - 是不是? [英] Raising C# events with an extension method - is it bad?

查看:245
本文介绍了用扩展方法提高C#事件 - 是不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们都很熟悉C#事件声明的恐怖。为了确保线程安全,标准是写这样的东西

 公共事件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 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)
其中T:EventArgs
{
var handler = @event;
if(handler!= null)
handler(sender,e);
}
}

使用这些扩展方法,您需要声明并提出事件是这样的:

 公共事件EventHandler SomethingHappened; 

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

我的问题:这是个好主意?我们是否缺少任何标准的On方法? (有一件事我注意到,它不适用于有明确的添加/删除代码的事件。)

解决方案

仍然使用明确的添加/删除的事件 - 您只需要使用委托变量(或者您已经存储委托),而不是事件名称。



但是,有一个更简单的方法来使其线程安全 - 使用no-op处理程序初始化它:

  public event EventHandler SomethingHappened = delegate {}; 

调用额外的委托的性能命中将是微不足道的,它确实使代码更容易。 / p>

顺便说一下,在扩展方法中,您不需要额外的本地变量 - 您可以执行以下操作:

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

static public void RaiseEvent< T>(this EventHandler< T> @event,对象发件人,T e)
其中T:EventArgs
{
if(@event!= null)
@event(sender,e);
}

我个人不会使用关键字作为参数名称, '真的改变了呼叫方,所以做你想要的:)



编辑:对于OnXXX方法:你计划你的类派生从?在我看来,绝大多数的班级应该是密封的。如果您执行,是否希望派生类能够提升事件?如果任何一个问题的答案是否,那么不要打扰。如果两者的答案是是,那么请执行以下操作:)


We're all familiar with the horror that is C# event declaration. To ensure thread-safety, 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);
}

Recently in some other question on this board (which I can't find now), someone pointed out that extension methods could be used nicely in this scenario. Here's one way to do it:

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

With these extension methods in place, all you need to declare and raise an event is something like this:

public event EventHandler SomethingHappened;

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

My question: Is this a good idea? Are we missing anything by not having the standard On method? (One thing I notice is that it doesn't work with events that have explicit add/remove code.)

解决方案

It will still work with events that have an explicit add/remove - you just need to use the delegate variable (or however you've stored the delegate) instead of the event name.

However, there's an easier way to make it thread-safe - initialize it with a no-op handler:

public event EventHandler SomethingHappened = delegate {};

The performance hit of calling an extra delegate will be negligible, and it sure makes the code easier.

By the way, in your extension method you don't need an extra local variable - you could just do:

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

Personally I wouldn't use a keyword as a parameter name, but it doesn't really change the calling side at all, so do what you want :)

EDIT: As for the "OnXXX" method: are you planning on your classes being derived from? In my view, most classes should be sealed. If you do, do you want those derived classes to be able to raise the event? If the answer to either of these questions is "no" then don't bother. If the answer to both is "yes" then do :)

这篇关于用扩展方法提高C#事件 - 是不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆