在C#中,你可以这样做:
if (Changed != null)
Changed(this, EventArgs.Empty);
但是你在VB.NET中做了什么?
有RaiseEvent
,但
RaiseEvent Changed(Me, EventArgs.Empty)
实际检查某事已订阅该事件?
答案 0 :(得分:14)
与其C#等价物不同,如果没有侦听器,VB.NET中的RaiseEvent
将不引发异常,因此首先执行空检查并非绝对必要。
但是如果你想这样做,那就有它的语法。您只需要将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撰写了一篇关于此here的精彩博客文章,其灵感来自this Stack Overflow question。
有趣的是,如果您检查使用RaiseEvent
关键字的反汇编VB.NET代码,您会发现它正在执行以上正确的 C#代码所做的事情:声明临时变量,执行空检查,然后调用委托。为什么每次都要混淆你的代码呢?
答案 1 :(得分: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)