23

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

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

MSDN 是这么说的:

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

但这并没有让我变得更聪明。密封的东西很明显。

注意:我已经看过虚拟事件在 C# 中的工作原理?问题,但这并不是关于虚拟事件如何运作的。而是那个人如何从使用它们中获得结果。试图从他的例子和答案中弄清楚虚拟事件是什么,但无法真正理解它。

4

3 回答 3

33

虚拟事件只是可以在派生类中覆盖的事件。

您是否对虚拟属性的概念感到满意,以及可以覆盖的 getter 和 setter?如果是这样,您可以以完全相同的方式考虑虚拟事件:除了 getter 和 setter,还有一个“添加”操作和一个“删除”操作。这些可以是虚拟的,因此可以多态处理。您实现它们的方式与实现任何其他虚拟/覆盖成员的方式相同。

例子:

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 本身具有引发的概念,但我们暂时忽略它。)

如果您对事件和委托之间的区别有点模糊,您可能还想阅读我关于事件的文章。

就我个人而言,我很少需要虚拟活动。

于 2009-07-14T20:38:01.283 回答
0

另请注意,在 C# 中,派生类无法触发纯粹在基类中定义的事件(无论它具有什么修饰符)。因此,我们需要为派生类创建一个新的或覆盖的事件,并且在大多数情况下,如果要触发相同的事件,则首选覆盖的事件。

于 2012-10-08T10:50:05.027 回答
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);
    }
}
于 2019-09-28T21:55:06.760 回答