在 C# 中转发事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1065355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 07:22:46  来源:igfitidea点击:

Forwarding events in C#

c#eventsevent-handlingc#-2.0

提问by user3891

I'm using a class that forwards events in C#. I was wondering if there's a way of doing it that requires less code overhead.

我正在使用一个在 C# 中转发事件的类。我想知道是否有一种方法可以减少代码开销。

Here's an example of what I have so far.

这是我到目前为止所拥有的一个例子。

class A
{
   public event EventType EventA;
}

class B
{
   A m_A = new A();
   public event EventType EventB;

   public B()
   {
      m_A.EventA += OnEventA;
   }

   public void OnEventA()
   {
      if( EventB )
      {
         EventB();
      }
   }
}

Class A raises the original event. Class B forwards it as EventB (which is essentially the same event). Class A is hidden from other modules so they can't subscribe to EventA directly.

A 类引发原始事件。B 类将其作为 EventB 转发(本质上是相同的事件)。A 类对其他模块是隐藏的,因此它们不能直接订阅 EventA。

What I'm trying to do is reduce the code overhead in class B for forwarding the event, as typically there's no real handling of the events in class B. Also I'll have several different events so it would require writing a lot of OnEvent() methods in class B that only serve to forward the events.

我想要做的是减少 B 类中转发事件的代码开销,因为通常没有真正处理 B 类中的事件。此外,我将有几个不同的事件,因此需要编写大量 OnEvent () 类 B 中仅用于转发事件的方法。

Is it possible to automatically link EventA to EventB in some way, so I'd have something like this:

是否可以以某种方式自动将 EventA 链接到 EventB,所以我有这样的事情:

class B
{
   A m_A = new A();
   public event EventType EventB;

   public B()
   {
      m_A.EventA += EventB; // EventA automatically raises EventB.
   }
}

I'm using a C# 2.0 compiler btw.

顺便说一句,我正在使用 C# 2.0 编译器。

采纳答案by Jon Skeet

Absolutely:

绝对地:

class B
{
    private A m_a = new A();

    public event EventType EventB
    {
        add { m_a.EventA += value; }
        remove { m_a.EventA -= value; }
    }
}

In other words, the EventB subscription/unsubscription code just passes the subscription/unsubscription requests on to EventA.

换句话说,Eve​​ntB 订阅/取消订阅代码只是将订阅/取消订阅请求传递给 EventA。

Note that this doesn't allow you to raise the event justfor subscribers who subscribed to EventB, however. It's like passing someone's address directly onto a mass marketing company, whereas your original way is more like subscribing to the mass marketing company yourself, and allowing people to ask you to send copies of the mails to them.

请注意,这不允许您仅为订阅 EventB 的订阅者引发事件。这就像将某人的地址直接传递给大众营销公司,而您的原始方式更像是自己订阅大众营销公司,并允许人们要求您将邮件的副本发送给他们。

回答by Marc Gravell

IMO, your original code is (more or less) correct. In particular, it allows you to provide the correct sender(which should be the Binstance for people who think they are subscribing to an event on B).

IMO,您的原始代码(或多或少)是正确的。特别是,它允许您提供正确的sender(这应该是B那些认为他们正在订阅事件的人的实例B)。

There are some tricks to reduce the overheads at runtime if the event isn't subscribed, but this adds morecode:

如果未订阅事件,则有一些技巧可以减少运行时的开销,但这会增加更多代码:

class B {
   A m_A = new A();
   private EventType eventB;
   public event EventType EventB {
       add { // only subscribe when we have a subscriber ourselves
           bool first = eventB == null;
           eventB += value;
           if(first && eventB != null) m_A.EventA += OnEventB;
       }
       remove { // unsubscribe if we have no more subscribers
           eventB -= value;
           if(eventB == null) m_A.EventA -= OnEventB;
       }
   }

   protected void OnEventB(object sender, EventArgsType args) {
      eventB?.Invoke(this, args); // note "this", not "sender"

   }
}