Should event firing in C# always be protected by a null check? - c#

This situation seem very interesting to me.
In C# you need to check if there is any listener to the event in a class before firing it.
Assuming event structure of C# is a non-standart(Meaning Microsoft did it) implementation of Observer observable pattern for ease of use.
Why didn't they implement this inside that structure? Is there solid reasons or documentation for this choice.
Is it a necessity do null checking, or am I wrong in my assumption for event structures needing null checks under all circumstances.
This is a more of a curiosity question looking for an answer to this implementation choice by microsoft. Which I hope will lead to further understanding of delegate and event keyword inner workings.

Yes, you must do the null check.
Calling a delegate that is null results in a NullReferenceException.
You might be tempted to intialize all delegates with a non-null, empty event handler. However, that would be far worse than testing for null, in terms of CPU usage, memory usage, and lines of code.

There's a reply to this question in a blog by Eric Gunnerson.
Basically it seems to say that Microsoft thought about changing it, but it would break existing code.
In other words, it was a mistake in the original design for events, but it's too late to fix it.

You can add a default event listener, thus avoiding the null check
public Action<object, EventArgs> SomeEvent = (o, e) => { };
in that way, you can call SomeEvent without checking for null, since it contains a default (empty implementation) listener. Please note that it might hurt performance.

Related

Is having default event initializer considered a good practice?

One thing that I find slightly annoying is having to null-check events. An event that has no subscribers is going to be null, so often times code like this has to be written:
MyEvent?.Invoke()
One solution for this problem I've found was this initialization pattern, where we initialize event with a no-op delegate:
public event Action MyEvent = delegate { };
Now, since this event is always going to have at least one dummy subscriber, we no longer have to check for null:
MyEvent.Invoke()
While this is pretty convenient, I was wondering whether this pattern a good practice, or is there some reason that I don't see that would make this a bad decision (aside from having to call an extra dummy subscriber, but I am fine with that)? Thanks.

Does adding trivial handler to event cause significant overhead?

From the content of the answer to this question I learned a new trick; to add a trivial handler to an event in order to avoid null checking when it is raised.
public static event EventHandler SomeEvent = delegate {};
and to invoke it without the null checking:
SomeEvent(null,EventArgs.Empty);
Does this add significant overhead? If not, why isn't something like this built in?
Does this add significant overhead? If not, why isn't something like this built in?
It doesn't add significant overhead - merely a delegate call when the event is raised.
As for why it's not built-in - there are a couple of downsides:
This isn't necessarily bullet proof - you can still clear the handler list afterwards, in which case, you'd still need the proper checking.
This does add overhead - while minor, that overhead could be problematic in specific scenarios.

Event handlers not thread safe? [duplicate]

This question already has answers here:
C# Events and Thread Safety
(15 answers)
Closed 10 years ago.
So i've read around that instead of calling a event directly with
if (SomeEvent != null)
SomeEvent(this, null);
i should be doing
SomeEventHandler temp = SomeEvent;
if (temp != null)
temp(this, null);
Why is this so? How does the second version become thread safe? What is the best practice?
IMO, the other answers miss one key detail - that delegates (and therefore events) are immutable. The significance of this is that subscribing or unsubscribing an event handler doesn't simply append/remove to a list - rather, it replaces the list with a new one with an extra (or one less) item on it.
Since references are atomic, this means that at the point you do:
var handler = SomeEvent;
you now have a rigid instance that cannot change, even if in the next picosecond another thread unsubscribes (causing the actual event field to become null).
So you test for null and invoke it, and all is well. Note of course that there is still the confusing scenario of the event being raised on an object that thinks it unsubscribed a picosecond ago!
Events are really syntactic sugar over a list of delegates. When you invoke the event, this is really iterating over that list and invoking each delegate with the parameters you have passed.
The problem with threads is that they could be adding or removing items from this collection by subscribing/unsubscribing. If they do this while you are iterating the collection this will cause problems (I think an exception is thrown)
The intent is to copy the list before iterating it, so you are protected against changes to the list.
Note: It is however now possible for your listener to be invoked even after you unsubscribed, so you should make sure you handle this in your listener code.
Best practice is the second form. The reason is that another thread might null or alter SomeEvent between the 'if' test and the invocation.
Here is a good write up about .NET events and race conditions with threads. It covers some common scenarios and has some good references in it.
Hope this helps.

Copying delegates

I was just reading a page on events on MSDN, and I came across a snippet of example code that is puzzling me.
The code in question is this:
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<CustomEventArgs> handler = RaiseCustomEvent;
I understand the intentions of the code, but I fail to see how that particular line is making a copy of anything. All it is doing is copying the reference; it's not actually making a deep copy of the delegate instance. So to that end, it doesn't actually prevent the race condition at all.
Am I missing something obvious here?
Delegates are immutable, so the reference obtained in that code is guaranteed to not change. If a user subscribes or unsubscribes after the null check, a new delegate will be created and set to the event. However, since you have a reference to a completely different object and invoke that, you don't have to worry about it being null.
You are correct; it is copying the reference.
However, delegates are immutable; when you add a handler to an event, a new delegate is created, combining the current handler(s) with the new one, and is then assigned to the field.
The Delegate instance that the field is referencing cannot change, so it does avoid the race condition.
Eric Lippert already covered this in a very detailed post.
This is from MSDN too..
"The invocation list of a delegate is an ordered set of delegates in which each element of the list invokes exactly one of the methods represented by the delegate. An invocation list can contain duplicate methods. During an invocation, methods are invoked in the order in which they appear in the invocation list. A delegate attempts to invoke every method in its invocation list; duplicates are invoked once for each time they appear in the invocation list. Delegates are immutable; once created, the invocation list of a delegate does not change."
if (whatever != null) whatever(); looks like it ensures that whatever is never null when whatever() is called, but it doesn't actually ensure that in a threaded scenario. A different thread can set whatever = null between the check and the call.
Foo temp = whatever;
if (temp != null) temp();
This code removes the possibility of the null dereference, since temp is a local and will therefore never be modified by a different thread. So it does prevent a race condition. It doesn't prevent all the relevant race conditions though. Eric Lippert did a more elaborate discussion of some other problems with the code.

Doing your own custom .NET event processing loop

A few years ago, I read a book that described how you could override the default event 'dispatcher' implementation in .NET with your own processor.
class foo {
public event EventHandler myEvent;
...
}
...
myFoo.myEvent += myBar1.EventHandler;
myFoo.myEvent += myBar2.EventHandler;
Whenever the event fires, both myBar1 and myBar2 handlers will be called.
As I recall, the default implementation of this loop uses a linked list and simply iterates over the list and calls the EventHandler delegates in order.
My question is two fold:
Does someone know which book I was reading?
Why would you want to override the default implementation (which might be answered in the book)?
Edit: The book I was referring to was indeed Jeffrey Richter's CLR via C#
It could have been one of many books or web articles.
There are various reasons why you might want to change how events are subscribed/unsubscribed:
If you have many events, many of which may well not be subscribed to, you may want to use EventHandlerList to lower your memory usage
You may wish to log subscription/unsubscription
You may wish to use a weak reference to avoid the subscriber's lifetime from being tied to yours
You may wish to change the locking associated with subscription/unsubscription
I'm sure there are more - those are off the top of my head :)
EDIT: Also note that there's a difference between having a custom way of handling subscription/unsubscription and having a custom way of raising the event (which may call GetInvocationList and guarantee that all handlers are called, regardless of exceptions, for example).
I seem to remember something similar in Jeffrey Richter's CLR via C#. Edit: I definitely do remember that he goes into detail about it.
There are a few different reasons for taking control of event registration. One of them is to reduce code bloat when you've got TONS of events. I think Jeffrey went into this in detail within the book...
No
You might, for example, need to break the call chain based on the result of one of the handlers. Say your CustomEventArgs object has a property 'Blocked', which when set to true suppresses all further event handler invocations.

Categories