在派生类的构造函数中添加事件处理程序,还是覆盖OnX()方法?

时间:2022-04-06 22:55:18

When designing a derived class, are there [dis]advantages to adding a handler to a base class event in the ctor vs overriding the OnEventName() method and adding some behaviour (as well as calling the base method), if one doesn't need to change the base method and doesn't care in what order things happen, but only wants a reusable component with a little extra behaviour?

当设计一个派生类,有[说]优势向基类添加一个处理程序事件男星vs覆盖OnEventName()方法和添加一些行为(以及调用基方法),如果一个人不需要变化的基本方法和不在乎什么事情发生,但只是想要一个可重用的组件和一些额外的行为呢?

base class:

public abstract class BaseClass
{
    public event EventHandler SomeEvent;
    protected void OnSomeEvent(object sender, EventArgs e)
    {
        // do some stuff
    }
}

option A:

public class DerivedA
{
    protected override void OnSomeEvent(object sender, EventArgs e)
    {
        // do some other stuff
        base.OnSomeEvent(sender, e);
    }
}

option B:

public class DerivedB
{
    public DerivedB()
    {
        SomeEvent += (o,e) => { // do some other stuff };
    }
}

2 个解决方案

#1


2  

You've already mentioned the order in which things are called. Some other things which admittedly don't happen all that often, but might be significant (based on the fact that the base class controls how the event handlers are invoked):

您已经提到了调用事物的顺序。其他一些事情当然不会经常发生,但可能很重要(基于基类控制如何调用事件处理程序的事实):

  • Event handlers might be called on a different thread;
  • 事件处理程序可以在不同的线程上调用;
  • Under some circumstances, the base class might choose not to call event handlers at all;
  • 在某些情况下,基类可能选择根本不调用事件处理程序;
  • The base class might catch specific types of exceptions thrown by handlers; exceptions thrown by your handler might be unintentionally swallowed.
  • 基类可能捕获处理程序抛出的特定类型的异常;您的处理程序抛出的异常可能会被无意地吞掉。

In general, I tend to see events as being there exclusively for a class's users, with a well-designed class having virtual On... methods for subclasses.

一般来说,我倾向于认为事件只存在于类的用户中,而设计良好的类具有virtual On…子类的方法。

#2


3  

There aren't any significant advantages/disadvantages to either approach.

这两种方法都没有明显的优缺点。

There's a few differences between subscribing to an event vs. overriding a base-class method. For example, if you want some code to run before or after all other handlers, you should really override the OnSomeEvent method, as there's no way to gaurantee that otherwise. But you indicate you don't really care about this.

订阅事件和覆盖基类方法之间有一些区别。例如,如果您希望在所有其他处理程序之前或之后运行一些代码,那么您应该真正覆盖OnSomeEvent方法,否则就无法对其进行约束。但你表明你并不真的在乎这个。

In general, overriding a method is something that requires a good understanding of the behavior of the base class to ensure that you don't inadvertantly break anything. Subscribing to an event is a less intrusive extensions, and is something that (presumably) the base class designer has planned for.

一般来说,重写方法需要很好地理解基类的行为,以确保不会不经意地破坏任何东西。订阅事件是一种较少打扰的扩展,并且(可能)是基类设计器计划要实现的。

Sometimes, people argue that performance is better when overriding - but I don't buy this argument. Performance only matters when it matters. The difference here is likely so negligible, that one should be more concerned with simplicity, correctness, and easy of maintenance over performance.

有时,人们会争辩说,当压倒一切的时候,表现会更好——但我不相信这种说法。表现只在重要的时候才重要。这里的差异可以忽略不计,因此应该更关注简单性、正确性和易于维护的性能。

#1


2  

You've already mentioned the order in which things are called. Some other things which admittedly don't happen all that often, but might be significant (based on the fact that the base class controls how the event handlers are invoked):

您已经提到了调用事物的顺序。其他一些事情当然不会经常发生,但可能很重要(基于基类控制如何调用事件处理程序的事实):

  • Event handlers might be called on a different thread;
  • 事件处理程序可以在不同的线程上调用;
  • Under some circumstances, the base class might choose not to call event handlers at all;
  • 在某些情况下,基类可能选择根本不调用事件处理程序;
  • The base class might catch specific types of exceptions thrown by handlers; exceptions thrown by your handler might be unintentionally swallowed.
  • 基类可能捕获处理程序抛出的特定类型的异常;您的处理程序抛出的异常可能会被无意地吞掉。

In general, I tend to see events as being there exclusively for a class's users, with a well-designed class having virtual On... methods for subclasses.

一般来说,我倾向于认为事件只存在于类的用户中,而设计良好的类具有virtual On…子类的方法。

#2


3  

There aren't any significant advantages/disadvantages to either approach.

这两种方法都没有明显的优缺点。

There's a few differences between subscribing to an event vs. overriding a base-class method. For example, if you want some code to run before or after all other handlers, you should really override the OnSomeEvent method, as there's no way to gaurantee that otherwise. But you indicate you don't really care about this.

订阅事件和覆盖基类方法之间有一些区别。例如,如果您希望在所有其他处理程序之前或之后运行一些代码,那么您应该真正覆盖OnSomeEvent方法,否则就无法对其进行约束。但你表明你并不真的在乎这个。

In general, overriding a method is something that requires a good understanding of the behavior of the base class to ensure that you don't inadvertantly break anything. Subscribing to an event is a less intrusive extensions, and is something that (presumably) the base class designer has planned for.

一般来说,重写方法需要很好地理解基类的行为,以确保不会不经意地破坏任何东西。订阅事件是一种较少打扰的扩展,并且(可能)是基类设计器计划要实现的。

Sometimes, people argue that performance is better when overriding - but I don't buy this argument. Performance only matters when it matters. The difference here is likely so negligible, that one should be more concerned with simplicity, correctness, and easy of maintenance over performance.

有时,人们会争辩说,当压倒一切的时候,表现会更好——但我不相信这种说法。表现只在重要的时候才重要。这里的差异可以忽略不计,因此应该更关注简单性、正确性和易于维护的性能。