An OnXYZ
method should always follow this form:
public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}
There are a couple of reasons for this form:
- The
if evt != null
check ensures that we don't try to invoke a null
delegate. This can happen if nobody has hooked up an event handler to the event.
- In a multithreaded scenario, since delegates are immutable, once we've obtained a local copy of the delegate into
evt
, we can safely invoke it after checking for non-null, since nobody can alter it after the if
but before the call.
What to pass for e
differs, if you need to pass an EventArgs
descendant with a parameter there are two ways:
public void OnXYZ(string p)
{
var evt = XYZ;
if (evt != null)
evt(sender, new SomeEventArgs(p));
}
or more commonly this:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
This syntax:
evt(sender, e);
is just a different way of writing this:
evt.Invoke(sender, e);
Also note that externally to your class, the event is an event, you can only add
or remove
event handlers from it.
Internal to your class, the event is a delegate, you can invoke it, check the target or method, walk the list of subscribers, etc.
Also, in C# 6 there is a new operator introduced, ?.
- the Null-conditional operator - which is basically short for if not-null, dereference
, which can shorten this method:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
into this:
public void OnXYZ(SomeEventArgs e)
{
XYZ?.Invoke(sender, e);
}
which can be further shortened with the use of Expression-bodied members:
public void OnXYZ(SomeEventArgs e) => XYZ?.Invoke(sender, e);
Please note that it is not possible to write this:
XYZ?.(sender, e);
so you must in this case use Invoke
yourself.