我复制。可以说,这是调试器中的一个错误,在我看来很难修复。将代码从 vb.net 反编译为 C# 时更容易看到。此示例代码:
Class Test
Public Event Foo As EventHandler
Public Event Bar As EventHandler
Public Sub Run(ByVal arg As Integer)
If arg = 0 Then
RaiseEvent Foo(Me, EventArgs.Empty)
Else
RaiseEvent Bar(Me, EventArgs.Empty)
End If
End Sub
End Class
被翻译成这个等效的 C# 代码:
public void Run(int arg)
{
EventHandler VB$t_ref$S0;
if (arg == 0)
{
VB$t_ref$S0 = this.FooEvent;
if (VB$t_ref$S0 != null)
{
VB$t_ref$S0(this, EventArgs.Empty);
}
}
else
{
VB$t_ref$S0 = this.BarEvent;
if (VB$t_ref$S0 != null) // <=== HERE!!!
{
VB$t_ref$S0(this, EventArgs.Empty);
}
}
}
当您使用 Set Next Statement 调试器命令将执行点设置到第二个 RaiseEvent 语句时,调试器会将执行点移动到上面代码片段中标记为 HERE 的语句。绕过临时变量的初始化。仍然为空,因此不会引发该事件。使用该命令后,您可以通过使用 Debug + Windows + Disassembly 查看机器代码来观察这种情况。
否则,这与任何 C# 程序员都非常熟悉的事件引发代码完全相同,他们没有引发事件访问器,因此必须编写以下代码:
var temp = Bar;
if (temp != null) {
Bar(this, EventArgs.Empty);
}
好吧,调试器搞砸了,很容易看出它是如何发生的。以及它是如何一直未被发现(或被忽略)的。变通办法很难找到,在 RaiseEvent 语句之前的语句会起作用,但非常不切实际。修改变量以使 If 语句执行所需的事件是可能的。
我在 connect.microsoft.com 上报告了这个问题,反馈文章在这里。不要期待奇迹。