Is there any smart way to avoid the verbosity of testing the nullity on an event before calling it in a generic way ? It looks obvious that if I call a delegate, I want it to be assigned.
(If I Really want/need to test its nullity I could eventually do it explicitly, but putting this test systematically is kind of tedious and verbose.)
public delegate void ResetTradesDelegate();
public ResetTradesDelegate ResetTradesEvents;
public void OnSessionRxAdmMessage(IVfxFixAppSession session, FixMessage msg)
{
if (ResetTradesEvent != null) //<-- Is there "any" a way not to write this test explicitly for each delegate ?
ResetTradesEvent();
}
public event EventHandler NoDataEventHandler = delegate{};
Declaring an event in this way means it will never be null. It will always, at a minimum, have a single no-op event handler hooked up.
In your case, probably
public event ResetTradesDelegate ResetTradesEvents = delegate{};
Firing an event is always going to have a race condition associated with it. You're either going to risk trying to call a delegate when it's null, or calling a delegate after the event has been unhooked. Eric Lippert wrote a pretty comprehensive post on this topic here. The technique above still suffers from the second type of race condition, so the event handlers need to be robust to being called after the event has been unhooked.
static void CallIfNotNull(this Action action)
{
if (action != null) action();
}
As an extension method, this is quite convenient to use.
You can create your event-handler with an always-subscribed no-op event:
public class MyClass
{
public MyClass()
{
this.Event += (sender, e) => ();
}
public event EventHandler Event;
protected virtual void OnEvent()
{
this.Event(this, EventArgs.Empty);
}
}
However, this requires subscribing your event and will incur a performance penalty as the no-op delegate will still exist in the list of subscribed event handlers.
My preference here is to create a pair of extension methods to invoke any event handler, whilst performing a null-safe check:
public static void Raise(this EventHandler @event, object sender)
{
if(@event != null)
{
@event.Invoke(sender, EventArgs.Empty);
}
}
public static void Raise<TEventArgs>(
this EventHandler<TEventArgs> @event,
object sender,
TEventArgs args)
where TEventArgs : EventArgs
{
if(@event != null)
{
@event.Invoke(sender, args);
}
}
This can then be easily invoked anywhere in your library to safely raise the event:
this.ResetTradesEvent.Raise(this);
It's purely syntactic sugar; you're still doing the check on the delegate. It is however, a nice re-usable way to wrap up this smelly part of the C# language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With