Reputation: 732
System.EventArgs implements a variant of the null object pattern - developers use EventArgs.Empty instead of null to designate a "nothing interesting here" situation, presumably in order to relieve the consumers of having to deal with possible null reference exceptions
I am declaring my own event with a derived event args class, say ContosoEventArgs
I think it would be only natural for consumers to be able to pass something like ContosoEventArgs.Empty
(just EventArgs.Empty
won't work as this would be an attempt to assign an instance of a base class to a variable of the derived class), as they are used to.
This, however, is tricky to implement - the Empty static property doesn't rely on some protected property IsEmpty that I can set in my derived class. If it did, I could do something like:
public class ContosoEventArgs : EventArgs
{
public static ContosoEventArgs Empty
{
get
{
return new ContosoEventArgs{IsEmpty=true};
}
}
}
Nice and clean!
However, such a property does not exist and to the best of my knowledge the only way to test EventArgs instance for Empty-ness is to compare to EventArgs.Empty. This means that I now need to implement operator == overload... and operator !=, and Equals(...), and GetHashCode()... all that boilerplate just to have my specialized event args follow the pattern from the base EventArgs
Should I instead just allow nulls? I think that's pretty much what they have done in the framework itself - MouseEventArgs and ImageClickEventArgs don't show traces of null object pattern implementation
Or am I overlooking some third option?
Upvotes: 0
Views: 325
Reputation: 4742
I think you could use this code without overloading equality members:
public class ContosoEventArgs : EventArgs
{
public new static readonly ContosoEventArgs Empty = new ContosoEventArgs();
}
If you look at the EventArgs, it uses the static instance to compare:
[ComVisible(true)]
[__DynamicallyInvokable]
[Serializable]
public class EventArgs
{
[__DynamicallyInvokable]
public static readonly EventArgs Empty = new EventArgs();
static EventArgs()
{
}
[__DynamicallyInvokable]
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public EventArgs()
{
}
}
Upvotes: 1