当前位置:  开发笔记 > 编程语言 > 正文

在事件处理程序中使用null check

如何解决《在事件处理程序中使用nullcheck》经验,为你挑选了3个好方法。

检查事件处理程序是否为null时,是否基于每个线程完成?

确保有人正在听这个事件就像这样:

EventSeven += new DivBySevenHandler(dbsl.ShowOnScreen);

如果我在上面检查null的模式之后添加代码,那么为什么我需要一个空检查(从这个站点获取的代码).我错过了什么?

此外,事件和GC的规则是什么?



1> Marc Gravell..:

问题是如果没有人订阅该事件,它就是null.并且你无法调用null.跳过三种方法:

检查为null(见下文)

添加"无所事事"处理程序: public event EventHandler MyEvent = delegate {};

使用扩展方法(见下文)

当空检查,是线程安全的,你必须在理论上首先捕捉委托引用(如果它的检查和调用不同的):

protected virtual void OnMyEvent() {
    EventHandler handler = MyEvent;
    if(handler != null) handler(this, EventArgs.Empty);
}

扩展方法具有不寻常的属性,它们可以在null实例上调用...

    public static void SafeInvoke(this EventHandler handler, object sender)
    {
        if (handler != null) handler(sender, EventArgs.Empty);
    }
    public static void SafeInvoke(this EventHandler handler,
        object sender, T args) where T : EventArgs
    {
        if (handler != null) handler(sender, args);
    }

然后你可以打电话:

MyEvent.SafeInvoke(this);

并且它是零安全的(通过检查)和线程安全的(通过仅读取一次引用).


喜欢通过堆栈上的隐含副本的线程安全性

2> Jon Skeet..:

我真的不清楚你的意思我害怕,但如果委托的可能性为null,你需要在每个线程上单独检查.通常你会这样做:

public void OnSeven()
{
    DivBySevenHandler handler = EventSeven;
    if (handler != null)
    {
        handler(...);
    }
}

这可以确保即使您EventSeven在课程期间的更改OnSeven()无法获得NullReferenceException.

但是你是对的,如果你肯定有一个订阅的处理程序,你不需要空检查.这可以通过"无操作"处理程序在C#2中轻松完成:

public event DivBySevenHandler EventSeven = delegate {};

另一方面,如果您可以从各种线程获得订阅,您可能需要某种锁定以确保您拥有"最新"处理程序集.我在我的线程教程中有一个例子可以提供帮助 - 尽管我通常建议尽量避免要求它.

在垃圾收集方面,事件发布者最终会引用事件订阅者(即处理程序的目标).如果发布者的寿命比订阅者长,这只是一个问题.


@HosseinNarimaniRad:它和答案中的例子一样安全,是的.C#的内存模型并不像它可能那样清晰,但基本上,我认为它是安全的.

3> unknown6656..:

我想附加一些关于C#6.0-Syntax的简短信息:

现在可以替换这个:

var handler = EventSeven;

if (handler != null)
    handler.Invoke(this, EventArgs.Empty);

有了这个:

handler?.Invoke(this, EventArgs.Empty);


将它与表达式成员组合,您可以缩短以下代码:

protected virtual void OnMyEvent()
{
    EventHandler handler = MyEvent;
    handler?.Invoke(this, EventArgs.Empty);
}

下到单线:

protected virtual void OnMyEvent() => MyEvent?.Invoke(this, EventArgs.Empty);


有关空条件运算符的更多信息,请参阅MSDN.
请参阅此博客关于表达式成员的信息

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有