这是一个更好的方式火/无C#中的空检查调用的事件?这是一个、事件、方式

2023-09-03 11:02:23 作者:望林间云去云来

大多数code我见过使用以下方法来声明并调用事件射击:

Most code I have seen uses the following way to declare and invoke event firing:

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的生成调用方法上面提到的方法。

Even ReSharper generates an invoking method the way mentioned above.

为什么不直接做这种方式:

Why not just do it this way:

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

任何人能解释的理由,为什么不这样做呢? (PRO与缺点)

Can anyone explain a reason why not to do this? (pro vs. cons)

推荐答案

的优点和缺点分别是:

null检查是非常便宜;我们谈论的十亿分之一秒的的。分配一个委托,然后垃圾收集失败它为对象的生命周期的其余部分可采取可能向上少数的百万分之一秒的。另外,你消耗的几十个字节的更多的内存。此外,每次事件触发的,你能说什么都不做的方法,不必要的电话,消费更加微秒。如果你是谁的人关心的百万分之一秒和几十个字节那么这可能是一个有意义的差异排序;对于情况下,它不会绝大多数。

null checks are extremely cheap; we're talking billionths of a second. Allocating a delegate and then garbage collecting it unsuccessfully for the rest of the lifetime of the object could take maybe upwards of a few millionths of a second. Plus, you're consuming dozens of bytes more memory. Plus, every time the event fires, you get an unnecessary call to a method that does nothing, consuming even more microseconds. If you're the sort of person who cares about millionths of a second and dozens of bytes then that might be a meaningful difference; for the vast majority of cases it will not.

您必须记住要始终创建空的委托。这真的是任何容易比记住要检查空?

You have to remember to always create the empty delegate. Is that really any easier than remembering to check for null?

无论是图案实际上使事件线程。它仍然是完全有可能与两个模式的事件处理程序被解雇的一个线程,而在另一个线程被删除,这意味着他们的比赛。如果您的处理程序清除code破坏状态的处理程序需要,那么很可能,而另一个线程运行处理一个线程被破坏的状态。 不要以为只是检查null或指定一个空的处理程序奇迹般地消除竞争。它不仅消除了竞争条件导致非关联化空。

Neither pattern actually makes the event threadsafe. It is still entirely possible with both patterns for an event handler to be fired on one thread while being removed on another thread, and that means that they race. If your handler removal code destroys state that the handler needs, then it is possible that one thread is destroying that state while another thread is running the handler. Do not think that merely checking for null or assigning an empty handler magically eliminates race conditions. It only eliminates the race condition that results in dereferencing null.

 
精彩推荐
图片推荐