8

在 C# 中,您可以执行以下操作:

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

但是你在 VB.NET 中做什么呢?

RaiseEvent,但是是

RaiseEvent Changed(Me, EventArgs.Empty)

实际检查是否有东西订阅了该事件?

4

2 回答 2

17

与它的 C# 等价物不同,RaiseEvent在 VB.NET 中,如果没有侦听器,则不会引发异常,因此没有必要首先执行 null 检查。

但是,如果你想这样做,它有一个语法。您只需Event在事件名称的末尾添加一个后缀即可。(如果你不这样做,你会得到一个编译器错误。)例如:

If ChangedEvent IsNot Nothing Then
    RaiseEvent Changed(Me, EventArgs.Empty)
End If

不过,就像我上面所说的那样,我不确定这样做是否有任何真正的好处。它使您的代码不习惯并且更难阅读。我在这里介绍的技巧并不是特别有据可查,大概是因为RaiseEvent关键字的全部意义在于在后台为您处理所有这些。这种方式更加方便和直观,这是 VB.NET 语言的两个设计目标。

您可能应该让它自动处理的另一个原因是因为在使用 C# 方式时很难正确处理它。您显示的示例片段实际上包含一个竞争条件,一个等待发生的错误。更具体地说,它不是线程安全的。您应该创建一个捕获当前事件处理程序集的临时变量,然后进行空检查。像这样的东西:

EventHandler tmp = Changed;
if (tmp != null)
{
    tmp(this, EventArgs.Empty);
}

Eric Lippert 在这里有一篇很棒的博客文章,灵感来自这个 Stack Overflow 问题

有趣的是,如果您检查使用该RaiseEvent关键字的反汇编 VB.NET 代码,您会发现它与上述正确的C# 代码所做的完全一样:声明一个临时变量,执行空值检查,然后调用委托。为什么每次都把你的代码弄得乱七八糟?

于 2013-05-23T11:30:49.303 回答
2

直接转换将是:

If Changed IsNot Nothing Then
    Changed(Me, EventArgs.Empty)
End If

但是 RaiseEvent必须用于在 VB.NET 中引发事件,不能简单地调用事件。RaiseEvent如果没有侦听器,则不会引发异常。

请参阅:http: //msdn.microsoft.com/en-GB/library/fwd3bwed (v=vs.71).aspx

因此,应使用以下内容:

RaiseEvent Changed(Me, EventArgs.Empty)
于 2013-05-23T10:18:07.393 回答