【发布时间】:2014-08-01 21:08:58
【问题描述】:
最近我发现虚拟事件在 C# 中并不像人们预期的那样工作。 考虑这段代码:
public abstract class MyClassBase
{
public virtual event EventHandler<EventArgs> MyEvent;
public void DoStuff()
{
if (MyEvent != null)
{
MyEvent(this, EventArgs.Empty);
}
}
}
public class MyClassDerived : MyClassBase
{
public override event EventHandler<EventArgs> MyEvent;
}
鉴于此定义,以下代码的行为与我预期的不同:
MyClassBase obj = new MyClassDerived();
obj.MyEvent += (s, e) => { /* Never gets called */ };
// Call method on base class that raises MyEvent
obj.DoStuff();
我已经完成了更广泛的write-up on my blog,但我只想说我找到了一个warning on MSDN,它确认了该行为是意外的,但它没有说明原因。谁能想到以这种方式实施的原因?它最初是为了向后兼容而留下的错误吗?我想至少可以添加某种编译器警告。
我意识到这很可能是猜测,但我正试图为这种奇怪的行为找到一个合理的解释。
【问题讨论】:
-
到底为什么要覆盖事件定义?我有点惊讶它甚至被允许:/
-
那么会发生什么,您认为应该发生什么,以及您认为应该发生什么?
-
只是一个建议:遵循示例代码中的正常大小写约定。
eventargs不是标准类型,但EventArgs是。同样,您的博客文章包含一个类型参数t,而T是常规的。这些不难解决,但会分散注意力。 -
@Thorarin:嗯?众所周知的事实是,MS 因其与向后兼容性有关的程度而受到敏捷性的影响……不知道这意味着什么。无论如何,那个飞碟烧了。
-
C# 编译器应该为此生成诊断。但是,是的,您总是必须对虚拟事件使用 add 和 remove 访问器。 那些方法是虚拟的,字段不能是虚拟的。