下面是我用来测试的程序。 它打印(如预期):
Raise A
Event from A
Raise B
Event from B
现在,如果我们将 Main 的前两行更改为:
A a = new B();
B b = new B();
程序将打印:
Raise A
Raise B
Event from B
这也是预期的,因为覆盖事件隐藏了基类中的私有(private)支持字段,因此基类触发的事件对派生类的客户端不可见。
现在我将相同的行更改为:
B b = new B();
A a = b;
然后程序开始打印:
Raise A
Raise B
Event from A
Event from B
这是怎么回事?
class A
{
public virtual event EventHandler VirtualEvent;
public void RaiseA()
{
Console.WriteLine("Raise A");
if (VirtualEvent != null)
{
VirtualEvent(this, EventArgs.Empty);
}
}
}
class B : A
{
public override event EventHandler VirtualEvent;
public void RaiseB()
{
Console.WriteLine("Raise B");
if (VirtualEvent != null)
{
VirtualEvent(this, EventArgs.Empty);
}
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
a.VirtualEvent += (s, e) => Console.WriteLine("Event from A");
b.VirtualEvent += (s, e) => Console.WriteLine("Event from B");
a.RaiseA();
b.RaiseB();
}
}
最佳答案
我们有一个(B 的)实例,它具有以下字段:
- A.VirtualEvent: null
- B.VirtualEvent:两个事件处理器
对 a.RaiseA()
的调用 只是 打印“Raise A” - 但仅此而已,因为 A 中的私有(private)字段为空。
调用 b.RaiseB()
打印剩余的三行,因为该事件已被订阅两次(一次打印“Event from A”,一次打印“Event from B” ).
这有帮助吗?
编辑:为了更清楚 - 将虚拟事件视为一对虚拟方法。它非常像这样:
public class A
{
private EventHandler handlerA;
public virtual void AddEventHandler(EventHandler handler)
{
handlerA += handler;
}
public virtual void RemoveEventHandler(EventHandler handler)
{
handlerA -= handler;
}
// RaiseA stuff
}
public class B : A
{
private EventHandler handlerB;
public override void AddEventHandler(EventHandler handler)
{
handlerB += handler;
}
public override void RemoveEventHandler(EventHandler handler)
{
handlerB -= handler;
}
// RaiseB stuff
}
现在更清楚了吗?它不是完全那样的,因为据我所知,您不能仅覆盖事件的“部分”(即其中一种方法),但它给出了正确的总体印象。
关于c# - 虚拟事件如何在 C# 中工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/714893/