C#:什么是虚拟事件以及它们如何使用?

时间:2009-07-14 20:32:29

标签: c# events inheritance virtual

虚拟活动如何运作?你会怎么覆盖它?那会怎么样?在什么情况下你会这样做?

例如,它是否可以替代受保护的OnEvent方法?那么继承类可以覆盖事件并直接引发它吗?或者这是错的还是不行?

MSDN对此有所说明:

  

可以使用virtual关键字将事件标记为虚拟事件。这使派生类可以使用override关键字覆盖事件行为。还可以密封覆盖虚拟事件的事件,该事件指定对于派生类,它不再是虚拟的。

但这并没有让我更加明智。密封的东西很明显。

注意: 我看过How virtual events work in C# ?问题,但实际上并不是虚拟事件的工作方式。相反,这个人是如何得到他们使用它们得到的结果。试图弄清楚他的例子和答案中的虚拟事件是什么,但不能真正理解它。

3 个答案:

答案 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);
    }
}