Tengo el siguiente escenario:
public abstract class SomeBaseClass { public event EventHandler SomeEvent; ... } public class SomeClass : SomeBaseClass { public void DoSomething() { //TODO if (SomeEvent != null) SomeEvent(this, EventArgs.Empty); } } SomeBaseClass tiene un evento que debe llamarse en una clase base; sin embargo, no es posible llamar directamente al evento desde una clase base. Para evitar esto, puedo anular el evento en la clase base, así:
public class SomeClass : SomeBaseClass { new public event EventHandler SomeEvent;Esto está bien, supongo, sin embargo, mi pregunta es si existe algún tipo de método universal o una buena práctica para implementar la funcionalidad anterior.
El hecho de que no sea posible llamar a un evento desde una clase base sugiere que en realidad no debería estar haciendo esto en primer lugar, ¿quizás la responsabilidad de llamar al evento debería estar solo en SomeBaseClass ?
Eso no está permitido de hecho. Si puedo recomendar un enfoque alternativo:
public abstract class SomeBaseClass { public event EventHandler SomeEvent; protected void RaiseSomeEvent(EventArgs e) { var eh = SomeEvent; if (eh != null) eh(this, e); } } public class SomeClass : SomeBaseClass { public void DoSomething() { //TODO RaiseSomeEvent(EventArgs.Empty); } } Tenga en cuenta que he movido la invocación del controlador de eventos a la clase propietaria, esto es requerido por .NET/C# ya que solo esa clase puede invocar el controlador de eventos. En segundo lugar, he hecho que el subproceso del controlador de eventos sea seguro asignándolo a eh primero.
¡ Nunca oculte el evento de la clase base usando la new palabra clave! Obtendrá resultados inesperados cuando use el tipo de la clase base como tipo para una variable o cuando la clase base invoque el evento.
Me mantendría alejado de usar new principalmente porque el código se comportará de manera diferente si un objeto se convierte en la clase base. Aquí hay una implementación alternativa:
public abstract class SomeBaseClass { public virtual event EventHandler SomeEvent; protected virtual void HandleSomeEvent() { var ev = SomeEvent; // Localize event field used if (ev != null) { ev(this, EventArgs.Empty); } } } public class SomeClass : SomeBaseClass { public override event EventHandler SomeEvent { add { base.SomeEvent += value; } remove { base.SomeEvent -= value; } } protected override void HandleSomeEvent() { base.HandleSomeEvent(); // ... My own code here } }Esto permite una gran flexibilidad. Puede proporcionar alguna implementación de manejo de eventos, así como permitir que el implementador anule por completo la implementación de la clase base.
public delegate void ErrorHandler(string result); public class BaseClass { public event ErrorHandler OnError; protected void RaiseErrorEvent(string result) { OnError?.Invoke(result); } } public class SampleClass:BaseClass { public void Error(string s) { base.RaiseErrorEvent(s); } }