这是在 C# 中无需进行空检查即可触发/调用事件的更好方法吗?

2023-12-24

我见过的大多数代码都使用以下方式来声明和调用事件触发:

public class MyExample
{
    public event Action MyEvent; // could be an event EventHandler<EventArgs>, too

    private void OnMyEvent()
    {
        var handler = this.MyEvent; // copy before access (to aviod race cond.)
        if (handler != null)
        {
            handler();
        }
    }

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing some things here
        OnMyEvent();
    }
 }

甚至 ReSharper 也会按照上述方式生成调用方法。

为什么不这样做:

public class MyExample
{
    public event Action MyEvent = delegate {}; // init here, so it's never null

    public void DoSomeThingsAndFireEvent() 
    {
        // ... doing some things here
        OnMyEvent(); // save to call directly because this can't be null
    }
 }

谁能解释为什么不这样做的原因? (优点与缺点)


优点和缺点是:

  • 空检查非常便宜;在说话十亿分之一一秒钟的时间。分配一个委托,然后在该对象的剩余生命周期内对其进行垃圾回收,可能需要花费一些时间百万分之一一秒钟的时间。另外,你正在消费几十个字节更多内存。另外,每次事件触发时,您都会不必要地调用一个不执行任何操作的方法,从而消耗更多微秒。如果您是那种关心百万分之一秒和几十个字节的人,那么这可能是一个有意义的差异;绝大多数情况下不会。

  • 您必须记住始终创建空委托。这真的比记住检查 null 更容易吗?

  • 这两种模式实际上都使事件成为线程安全的。这两种模式仍然完全有可能在一个线程上触发事件处理程序,同时在另一个线程上删除事件处理程序,这意味着它们会发生竞争。如果您的处理程序删除代码破坏了处理程序所需的状态,则一个线程可能正在破坏该状态,而另一个线程正在运行该处理程序。不要认为仅仅检查 null 或分配一个空处理程序就可以神奇地消除竞争条件。它只是消除了导致取消引用 null 的竞争条件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这是在 C# 中无需进行空检查即可触发/调用事件的更好方法吗? 的相关文章

随机推荐