虚拟事件如何在 C# 中工作?

How virtual events work in C#?(虚拟事件如何在 C# 中工作?)
本文介绍了虚拟事件如何在 C# 中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我用于测试的程序.它打印(如预期):

Below is the program I used for the test. It prints (as expected):

Raise A
Event from A
Raise B
Event from B

现在,如果我们将 Main 的前两行更改为:

Now, if we change first two lines of the Main to be:

        A a = new B();
        B b = new B();

程序将打印:

Raise A
Raise B
Event from B

这也是意料之中的,因为覆盖事件隐藏了基类中的私有支持字段,因此基类触发的事件对派生类的客户端不可见.

which is also expected, as overriding event hides the private backing field in the base class and therefore events fired by the base class are not visible to clients of the derived class.

现在我将相同的行更改为:

Now I am changing the same lines to:

 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的)实例,它具有以下字段:

We have a single instance (of B) which has the following fields:

  • A.VirtualEvent: null
  • B.VirtualEvent:两个事件处理程序

a.RaiseA() 的调用 只是 打印Raise A" - 仅此而已,因为 A 中的私有字段为空.

The call to a.RaiseA() just prints "Raise A" - but nothing more, because the private field in A is null.

b.RaiseB() 的调用会打印剩余的三行,因为该事件已被订阅了两次(一次打印来自 A 的事件",一次打印来自 B 的事件").

The call to b.RaiseB() prints the remaining three lines, because the event has been subscribed to twice (once to print "Event from A" and once to print "Event from B").

这有帮助吗?

为了更清楚 - 将虚拟事件视为一对虚拟方法.很像这样:

To make it clearer - think of the virtual event as a pair of virtual methods. It's very much like this:

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
}

现在更清楚了吗?这不是完全那样,因为据我所知,您不能只覆盖事件的部分"(即其中一种方法),但它给人的总体印象是正确的.

Now is it clearer? It's not quite like that because as far as I'm aware you can't override just "part" of an event (i.e. one of the methods) but it gives the right general impression.

这篇关于虚拟事件如何在 C# 中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)