虚拟活动如何运作?你会怎么覆盖它?那会怎么样?在什么情况下你会这样做?
例如,它是否可以替代受保护的OnEvent方法?那么继承类可以覆盖事件并直接引发它吗?或者这是错的还是不行?
MSDN对此有所说明:
可以使用virtual关键字将事件标记为虚拟事件。这使派生类可以使用override关键字覆盖事件行为。还可以密封覆盖虚拟事件的事件,该事件指定对于派生类,它不再是虚拟的。
但这并没有让我更加明智。密封的东西很明显。
注意: 我看过How virtual events work in C# ?问题,但实际上并不是虚拟事件的工作方式。相反,这个人是如何得到他们使用它们得到的结果。试图弄清楚他的例子和答案中的虚拟事件是什么,但不能真正理解它。
答案 0 :(得分:27)
虚拟事件只是在派生类中重写 的事件。
您是否对虚拟财产的概念感到满意,使用可以覆盖的getter和setter?如果是这样,你可以用完全相同的方式来思考虚拟事件:而不是getter和setter,它有一个“add”操作和一个“remove”操作。这些可以是虚拟的,因此可以进行多态处理。您可以像实现任何其他虚拟/重写成员一样实现它们。
示例:
using System;
class Base
{
public virtual event EventHandler Foo
{
add
{
Console.WriteLine("Base Foo.add called");
}
remove
{
Console.WriteLine("Base Foo.remove called");
}
}
}
class Derived : Base
{
public override event EventHandler Foo
{
add
{
Console.WriteLine("Derived Foo.add called");
}
remove
{
Console.WriteLine("Derived Foo.remove called");
}
}
}
class Test
{
static void Main()
{
Base x = new Derived();
x.Foo += (sender, args) => {};
}
}
请注意,事件本身不对引发它时发生的事情负责 - 只是添加/删除方面。 (无论如何,在C#中; CLR本身有提升的概念,但我们暂时会忽略它。)
如果您对某个活动与代表之间的差异略微模糊,您可能还想阅读my article on events。
我个人觉得非常很少,我想要一个虚拟活动。
答案 1 :(得分:0)
另请注意,在C#中,派生类无法触发纯粹在基类中定义的事件(无论它具有什么修饰符)。因此,我们需要为派生类创建一个新事件或重写事件,并且在大多数情况下,如果要触发相同的事件,则首选覆盖事件。
答案 2 :(得分:0)
要提出Foo
,我发现在接受的答案中缺少2个选择。
public class Base
{
public virtual event EventHandler Foo;
public void Bar()
{
RaiseFoo();
}
protected virtual void RaiseFoo()
{
Foo?.Invoke(this, EventArgs.Empty);
}
}
public class Derived : Base
{
// In this case we use the base Foo as a backing store.
public override event EventHandler Foo
{
add { base.Foo += value; }
remove { base.Foo -= value; }
}
}
public class Derived2 : Base
{
public override event EventHandler Foo;
// In this case we raise the overriden Foo.
protected override void RaiseFoo()
{
Foo?.Invoke(this, EventArgs.Empty);
}
}
class Test
{
static void Main()
{
Base x = new Derived();
x.Foo += (sender, e) => { };
x.Bar();
Base x2 = new Derived2();
x2.Foo += (sender, e) => { };
x2.Bar();
}
}
请注意,这不起作用:
public class Derived3 : Base
{
public override event EventHandler Foo
{
add { base.Foo += value; }
remove { base.Foo -= value; }
}
protected override void RaiseFoo()
{
Foo?.Invoke(this, EventArgs.Empty);
}
}