简体   繁体   English

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

[英]C#: What are virtual events and how can they be used?

How does a virtual event work?虚拟活动如何运作? How would you override it?你会如何覆盖它? How would that work?这将如何运作? And in what cases would you do that?在什么情况下你会这样做?

Would it for example be an ok replacement for protected OnEvent methods?例如,它可以替代受保护的 OnEvent 方法吗? So that inheriting classes could just override the event and raise it directly?那么继承类可以覆盖事件并直接引发它吗? Or would that be wrong or just not work?或者那会是错误的还是行不通的?

The MSDN says this about it: MSDN 是这样说的:

An event can be marked as a virtual event by using the virtual keyword.可以使用 virtual 关键字将事件标记为虚拟事件。 This enables derived classes to override the event behavior by using the override keyword.这使派生类能够使用 override 关键字覆盖事件行为。 An event overriding a virtual event can also be sealed, which specifies that for derived classes it is no longer virtual.覆盖虚拟事件的事件也可以被密封,它指定对于派生类它不再是虚拟的。

But that didn't make me much wiser.但这并没有让我变得更聪明。 The sealed stuff is obvious though.密封的东西很明显。

Note: I've seen the How virtual events work in C# ?注意:我已经看过C# 中的虚拟事件如何工作? question, but it wasn't really about how virtual events work.问题,但这并不是关于虚拟事件的工作原理。 Rather it was how that person got the result he got from using them.而是那个人如何获得他从使用它们中得到的结果。 Tried to figure out what virtual events were from his example and the answers, but couldn't really make sense out of it.试图从他的例子和答案中找出虚拟事件是什么,但无法真正理解它。

A virtual event is simply one which can be overridden in a derived class.虚拟事件只是一个可以在派生类中覆盖的事件。

Are you happy with the concept of a virtual property, with a getter and setter which can be overridden?您对虚拟财产的概念感到满意,可以覆盖 getter 和 setter 吗? If so, you can think of a virtual event in exactly the same way: instead of a getter and setter, there's an "add" operation and a "remove" operation.如果是这样,您可以以完全相同的方式考虑虚拟事件:不是 getter 和 setter,而是“添加”操作和“删除”操作。 These can be virtual, so handled polymorphically.这些可以是虚拟的,因此可以多态处理。 You implement them the same way you implement any other virtual/overridden member.您可以像实现任何其他虚拟/覆盖成员一样实现它们。

Example:例子:

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) => {};
    }
}

Note that the event itself is not responsible for what happens when it is raised - just the add/remove side.请注意,事件本身不对引发时发生的事情负责 - 只是添加/删除方面。 (In C#, anyway; the CLR itself has the notion of raising, but we'll ignore that for the moment.) (无论如何,在 C# 中;CLR 本身有提升的概念,但我们暂时忽略它。)

You may also want to read my article on events if you're slightly hazy on the difference between an event and a delegate.如果您对事件和委托之间的区别有点模糊,您可能还想阅读我关于事件的文章

Personally I find it very rare that I want a virtual event.就个人而言,我发现我想要一个虚拟活动是非常罕见的。

Also note that in C# a derived class is not able to fire the event purely defined in base class (no matter what modifier it has).另请注意,在 C# 中,派生类无法触发纯粹在基类中定义的事件(无论它具有什么修饰符)。 So we either need have a new or overriding event for the derived class and in most cases an overriding one is preferred if the same event is meant to be fired.因此,我们需要为派生类创建一个新事件或覆盖事件,并且在大多数情况下,如果要触发相同的事件,则首选覆盖事件。

For Foo to be raised there are 2 alternatives which I find missing from the accepted answer.对于要提出的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();
    }
}

Note that this doesn't work:请注意,这不起作用:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM