如何虚拟事件在C#中工作? [英] How virtual events work in C#?

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

问题描述

下面是我用于测试程序。
它打印(如预期):

 提出一个
从A事件
抬起B.
从B事件

现在,如果我们改变主要的前两行是:

  A A =新的B();
        B B =新的B();

该程序将打印:

 提出一个
抬起B.
从B事件

这也是意料之中的,因为压倒一切的大事隐藏的私人支持字段在基类中,因此,在基类触发的事件是不可见的派生类的客户。

现在我改变了同样的话:

  B B =新的B();
 一个A = B;

和程序启动打印:

 提出一个
抬起B.
从A事件
从B事件

这是怎么回事?

  A级
{
    公共虚拟活动的EventHandler VirtualEvent;
    公共无效RaiseA()
    {
        Console.WriteLine(升A);
        如果(VirtualEvent!= NULL)
        {
            VirtualEvent(这一点,EventArgs.Empty);
        }
    }
}
B类:一
{
    公共覆盖事件的EventHandler VirtualEvent;
    公共无效RaiseB()
    {
        Console.WriteLine(提高B);
        如果(VirtualEvent!= NULL)
        {
            VirtualEvent(这一点,EventArgs.Empty);
        }
    }
}类节目
{
    静态无效的主要(字串[] args)
    {
        A中新= A();
        B B =新的B();        a.VirtualEvent + =(S,E)=> Console.WriteLine(从事件);
        b.VirtualEvent + =(S,E)=> Console.WriteLine(事件选自B);        a.RaiseA();
        b.RaiseB();
    }
}


解决方案

我们有(乙)的单个实例有以下字段:


  • A.VirtualEvent:空

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

要调用 a.RaiseA()只是的版画升A - 但仅此而已,因为在私有字段为空

b.RaiseB()打印剩下的三条线,因为该事件已订阅两次(一次打印从事件,并一次通话打印从B事件)。

帮助吗?

编辑:为了更清楚 - 认为虚拟事件作为对虚拟方法。这非常像这样的:

 大众A级
{
    私人事件处理handlerA;    公共虚拟无效的addEventHandler(事件处理程序处理程序)
    {
        handlerA + =处理程序;
    }    公共虚拟无效RemoveEventHandler(事件处理程序处理程序)
    {
        handlerA - =处理程序;
    }    // RaiseA东西
}公共B类:一
{
    私人事件处理handlerB;    公共覆盖无效的addEventHandler(事件处理程序处理程序)
    {
        handlerB + =处理程序;
    }    公共覆盖无效RemoveEventHandler(事件处理程序处理程序)
    {
        handlerB - =处理程序;
    }    // RaiseB东西
}

现在是更清楚?这不是的非常的一样,因为据我所知,你不能覆盖只是一个事件的部分(即的方法之一),但它给出正确的一般IM pression

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

Raise A
Event from A
Raise B
Event from B

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

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

the Program will print:

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;

and the program starts printing:

Raise A
Raise B
Event from A
Event from B

What's going on?

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

解决方案

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

  • A.VirtualEvent: null
  • B.VirtualEvent: Two event handlers

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

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").

Does that help?

EDIT: 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#中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆