Microsoft's tutorial on events shows how to check an event for null before triggering it:
protected virtual void OnChanged(EventArgs e)
{
if (Changed != null)
{ // Potential Race-condition at this point!
Changed(this, e);
}
}
But this leaves open a race-condition, as detailed in Eric Lippert's blog, where he writes that events should be triggered via a local event to avoid a race-condition:
protected virtual void OnChanged(EventArgs e)
{
ChangedEventHandler temp = Changed; // Local copy of the EventHandler
if (temp != null)
{ // Race condition avoided by local variable.
temp(this, e);
}
}
While this works, it has confused many developers who get it wrong, and don't put it in the locally-scoped event.
Another solution, from DailyCoding is to always initialize your event to have one empty handler, so a null-check is never needed:
// Set with empty delegate, will never be null
public event ChangedEventHandler Changed = delegate { };
protected virtual void OnChanged(EventArgs e)
{
// Neither Null-check nor local variable is needed; just trigger the event.
Changed(this, e);
}
This one makes a lot of sense, and is pretty simple.
However, since I see this technique so rarely mentioned online, I think there must be a reason why.
Is there a downside to initializing an event with an empty delegate like this?
You will see an absolutely tiny performance hit, but there are problems in more advanced cases, for example serializing and deserializing the class could lead to you losing the fake event handler, and the lack of a null check then throwing an exception.
It's a slight performance hit if the event would have been empty
If you ever write Changed = null in the class, it will break.
In Eric Lippert's blog article you posted, he says:
There are other ways to solve this problem; for example, initializing
the handler to have an empty action that is never removed. But doing a
null check is the standard pattern.
But before that he also says:
Removing the code around the call site [the null check] does not decrease the number of race conditions in the code [...]. Worse, doing so makes the race condition harder to detect by
shrinking the window in which the race can occur without eliminating
it.
This is because as he describes, it can still happen
Between the push of the delegate value [onto the stack] and the call to invoke it [...]
So basically, if you use an empty handler, you experience some performance loss (this seems to be the consensus here). So you're what you're gaining is readability, but most importantly: weird behavior will be more apparent. (I deduce this from less performance -> takes longer -> more likely to invoke stale handler)
So if you're fully aware that things like these can happen, and the null checking doesn't bother you, go for it. Or don't, if you don't want to.
Related
I have the following code and am wondering how to break it down? It works great but was written by a guru and is over my head. Thank you in advance for any help.
The code basically writes device information sent and received to the GUI. It seems like it has events created based on the device and also invokes GUI stuff.
Why would you need to invoke?
I guess I'm wondering if this is overly complicated or appropriate? What may be a better way to accomplish the same task?
I'm also wondering what the "delegate { };" does?
public event EventHandler CommunicationPerformed = delegate { };
SerialPort _port;
readonly int _delay = 100;
private string ReadAndUpdateStatus()
{
string read = _port.ReadExisting();
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));
return read;
}
private void WriteAndUpdateStatus(string data)
{
if (!data.StartsWith("//")) //ignore "Comment" lines but show them on the GUI to read
_port.Write(data);
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(data, LoaderCommunicationDirection.Write));
}
public class LoaderReadWriteEventArgs : EventArgs
{
public LoaderCommunicationDirection Direction { get; }
public string Value { get; }
public LoaderReadWriteEventArgs(string value, LoaderCommunicationDirection direction)
{
Value = value;
Direction = direction;
}
}
public enum LoaderCommunicationDirection
{
Read,
Write
}
You asked three questions, and as usual, only one of them got answered. Try to ask only one question in your question.
I'm also wondering what the delegate { } does?
public event EventHandler CommunicationPerformed = delegate { };
As the other answer notes, events are null by default in C#. This technique makes an event handler that does nothing, but is not null.
There are, unfortunately, many syntaxes for an anonymous function in C#. delegate {} means "give me a do-nothing function that matches any non-ref-out formal parameter list that is void returning". That's why people do delegate{}, because it works almost anywhere in a context where an event handler is expected.
I think you need to review this https://learn.microsoft.com/en-us/dotnet/standard/events/.
Why would you need to invoke?
To broadcast to event handlers (any party who registered for this event get notified this way)
I guess I'm wondering if this is overly complicated or appropriate?
*What may be a better way to accomplish the same task?
This is not complicated. This is pretty much as easy as it gets.*
I'm also wondering what the "delegate { };" does?
my two cents.
I dont know which code line you are refering but a delegate is a type that holds a reference to a method. A delegate is declared with a signature that shows the return type and parameters for the methods it references, and can hold references only to methods that match its signature. A delegate is thus equivalent to a type-safe function pointer or a callback. A delegate declaration is sufficient to define a delegate class.
orhtej2 answered your first question quite nicely. Using the explicit Invoke method allows you to leverage the null conditional operator, which reduces the code to fire the event a single line.
As for whether this is overly complicated: No, that's basically how events are done.
What I've sometimes seen (especially in combination with the INotifyPropertyChanged interface in MVVM patterns) are helper methods, which encapsulate the longer, but more obvious pre-C#6 code and let you fire the event with less plumbing.
private void FireCommPerformed(string value, LoaderCommunicationDirection direction)
{
EventHandler handler = CommunicationPerformed;
if (handler != null)
{
handler(this, new LoaderReadWriteEventArgs(value, direction)));
}
}
You could then use it like this:
private string ReadAndUpdateStatus()
{
string read = _port.ReadExisting();
FireCommPerformed(read, LoaderCommunicationDirection.Read);
return read;
}
The Delegate { } is simply an empty delegate, like a null for events. Unless some other method in the code subscribes to the CommunicationPerformed event of this class during runtime, nothing will happen when the event is fired.
Let's focus in on what is exactly happening here. This should help you figure out everything else.
CommunicationPerformed?.Invoke(this, new LoaderReadWriteEventArgs(read, LoaderCommunicationDirection.Read));
This is checking to see if the delegate (event handlers are delegates) (CommunicationPerformed) is null.
Delegates are pointers (but with extra functionality).
If the delegate (pointer) is null, it means that nothing has been assigned to it.
Pointers store memory locations. In this case, it makes a memory reference to the function 'this'. 'This' is a reference to ReadAndUpdateStatus().
So this line basically says: "since the pointer is null, have this pointer reference the ReadAndUpdateStatus() function".
But what about the event args? Well... This is where delegates diverge from pointers.
Delegates don't just safely hold and store memory locations. They also can hold parameters.
You use a class that extends from EventArgs as the way of passing in a list of parameters.
From here, the event handler (event handlers are delegates) CommunicationPerformed will coordinate sending that list of arguments to whatever functions require it.
These functions are called whenever CommunicationPerformed is invoked (e.g. told to run). This is typically indicated with a:
+=CommunicationPerformed(foo,bar)
Now - why would use event handlers (or any delegate - for that matter)?
They're verbose and annoying to read (way more work than writing a simple bool and a trigger function), they don't look like other function, and they're frankly weird - right?
Except that they're really useful. Here's how:
1.) They work a lot like Tasks. You can invoke them in Parallel, in loops, wherever. They keep consistent state. They don't "bleed" and cause bugs.
2.) They're pointers. Guaranteed pass-by-reference. Except, they're magical, and if you stop using the delegate, they won't linger in memory.
3.) They allow you to control state in loops. Sometimes, a bool trigger won't work properly if you're in a really tight loop. You fire an event? Guaranteed behavior that your trigger will only be fired once.
I'm gonna try to answer #1 and #2 (3 is already covered).
#1 - At some point, someone decided that other parts of the program could subscribe to an event that tells them when communication has been performed. Once that decision has been made, it's kind of a "contract". You perform the communication->you fire the event that notifies subscribers that communication has been performed. What those subscribers are doing about that, or why they need to know...Actually not really any of your concern if this class is your focus. In theory, at least. And often that's really practically the case. If your class is doing its job, it's not really your concern who is listening to the events.
#2 - I do think the method of declaring events and event handlers in your code is overly complicated. Plenty of people (and official Microsoft best practices) disagree with me. You can google "why should my event handlers use eventargs" and read plenty on the subject. Or Look here. Another approach is the following:
public event Action<string, LoaderCommunicationDirection> CommunicationPerformed;
void PerformWrite()
{
string myComm = "String I'm sending";
//Line of code that performs communication that writes string here
CommunicationPerformed?.Invoke(myComm, LoaderCommunicationDirection.Write);
}
This is much more succinct than having an entire class that derives from EventArgs. However, it has the very obvious drawback that if you are an event subscriber...you have no idea what string is. Of course, since it's named value in your code...that's not much more helpful. And a comment above the event declaration is just about as useful.
Suppose there is the following code snippet (I am using .NET 4.0):
private void CauseTrouble()
{
if (MyEvent != null)
{
DoSomeIrrelevantCalculations();
MyEvent();
}
}
When running a fairly large program containing this (simplified) method, in rare cases I encounter a NullReferenceException from MyEvent(). The debugger tells me that MyEvent is null even though I just checked that it is not null. What is going on here?
Now some people might immediately say: "Of course, if you have a multithreaded application, another thread might unregister myEvent before those irrelevant calculations are finished and - Boom! - you have a NullReferenceException!"
That is surely true, but before I venture deeper into the darkness of multithreading (since it is a very rare error, I often have to wait days for it to occur again), I need to know if there are any other possibilities for this to happen?
Specifically: Does an event being null after a successful non-null check necessarily mean that another thread has unregistered the event?
(Another option I could imagine is the external unmanaged code which is executed by the program as well and which has already caused some data access violations before. Is it possible that some operation there is causing the pointer to MyEvent to be overwritten? Or should this be impossible since the code snippet is part of the managed code? I am too inexperienced with that stuff to be able to tell.)
If you say now: Hey, why do you not log all register/unregister processes and check what is going on yourself: You are right. I am already on it. But as I said, with a bit bad luck it can take a week before I get an answer, and I want to check out other possibilities as well in the meantime.
Update
Things get stranger. The assumption was correct, the debugger shows that MyEvent is indeed null when being called. So I did what was recommended here and replaced
if (MyEvent != null)
{
DoSomeIrrelevantCalculations();
MyEvent();
}
with
var handler = MyEvent;
if (handler != null)
{
DoSomeIrrelevantCalculations();
handler();
}
But this still yields a NullReferenceException. Debugging shows that MyEvent is again null when handler() is called, but handler itself is not. How can a NullReferenceException be evoked if the object is not even null?
You have two options. If you're working in C# 6.0 or higher, you can use the null coalescing operator. Behind the scenes, it'll prevent this problem from happening. Here's how:
MyEvent?.Invoke();
The other option is useful if you're not using C# 6.0. Just store it in a variable first, check the variable, and then invoke it using the local variable, like this:
var eventHandler = MyEvent;
if (eventHandler != null)
{
eventHandler();
}
I often see code like the following, and wonder if there is any reason for using a local variable for the event, instead of just using the event itself. Is there?
var handler = OnQueryComplete;
if (handler != null)
handler(this, new RepositoryEventArgs<T>(results));
Yes, absolutely - it makes the nullity check safe.
If you just have:
// Bad code, do not use
if (OnQueryComplete != null)
{
OnQueryComplete(this, ...);
}
then the last subscriber may unsubscribe between the check and the invocation, causing a NullReferenceException.
There are lots of options here:
Decide that you don't care about thread safety, even to the extent of it throwing an exception. (In many cases this may be reasonable, particularly if this is all your own codebase.)
Use an extension method to make this simple to achieve so the nullity check goes away anyway.
In C# 6, use the conditional null operator:
OnQueryComplete?.Invoke(this, ...);
Set up the event with a single empty handler which is never removed:
public event FooEventHander OnQueryComplete = delegate {};
You may also want to use Interlocked to make sure you've got the most recent value of the variable, to avoid memory model issues. See my blog post (including comments) for more discussion of this.
Very basic question, so I'm just looking for a best practice to follow.
My class has a few events which should be subscribed to. (e.g. DiscoveryCompleted). Within the method I do check if the event is null or not, however I'm not sure if I should raise an exception, if so what type. NotImpletementedException?
If the exception is unhandled it doesnt look very elegant.
Your thoughts?
My thought is this is precisely what the NotImplementedException was created for. You should never encounter a NotImplementedException in production code, but it makes it painfully clear during testing that you have a code path that has, well, not been implemented.
Kinda like a TODO comment, but more in-your-face :)
Although, I might question whether having an event handler that must be subscribed to, and not having a default subscriber, doesn't indicate a design issue.
EDIT
I think I misunderstood your initial question slightly, based on your comment. As others have stated (and I questioned), you should not be throwing an exception when you don't have a subscriber to an event handler; simply don't try to call it. If no one cares that event x happened, you can't really do anything about that.
It's not your code's responsibility to care whether anyone cares that it happened, but simply to notify them that it happened if they do care.
EDIT 2 - now with more code
public interface INeedToKnowAboutSomethingImportant
{
void WhenSomethingImportantHappens(SomethingImportantHappenedEventArgs args);
}
public class DoesSomethingImportant
{
private readonly INeedToKnowAboutSomethingImportant _needyDependency;
public DoesSomethingImportant(INeedToKnowAboutSomethingImportant needyDependency)
{
_needyDependency = needyDependency;
}
protected void SomethingImportantHappened(object sender, EventArgs e)
{
//Handle internally
_needyDependency.WhenSomethingImportantHappens(new SomethingImportantHappenedEventArgs(e));
}
}
Following this pattern, you don't have to worry about whether anyone is subscribed to your event handlers. You have to fulfill the dependency, but it doesn't matter AT ALL what you fill it with because whatever it is, it will have that method for you to call.
Events should be optionally subscribed to.
If your class has to call a method, pass a delegate on its constructor instead.
You should not throw NotImplementedException when you check your event. Just check, and execute if not null.
Take for instance. You put an element on your page, but you do not intend to implement any events on the button. The button check for Click event, don't find one, and throws NotImplementedException.
Now that is just wrong.
Event is something that's raised when a certain point the program is hit. Then you can have code that is "triggered" by it. The main path of the code should not be affected whether an event is present or not. If the main path of your code cannot continue without the event being triggered, then you need to use a Method instead.
My suggestion is:
1) Create an event.
2) Subscribe the event with handlers that you are going to implement later.
3) Throw the NotImplementedException in the handler.
As for exception is unhandled, you should never be handling NotImplementedException anyway :P... (And you shouldn't be throwing NotImplementedException for null reference to events).
You should not worry about the event object being null. If no one has subscribed to the event then nothing. If you need another function to run outside of your event raising class, then you need to use another pattern besides the observer pattern. As Eduardo suggested you can pass in a delegate, you might also consider a builder pattern.
I would not throw if an event has no subscribers.
In the "On" method that raises the event you will need a null test (note the race condition prevention). Elsewhere your class should not assume that the event has subscribers.
Evil or not evil?
public static void Raise(this EventHandler handler, object sender, EventArgs args)
{
if (handler != null)
{
handler(sender, args);
}
}
// Usage:
MyButtonClicked.Raise(this, EventArgs.Empty);
// This works too! Evil?
EventHandler handler = null;
handler.Raise(this, EVentArgs.Empty);
Note that due to the nature of extension methods, MyButtonClicked.Raise will not throw a NullReferenceException if MyButtonClicked is null. (E.g. there are no listeners to MyButtonClicked event).
Evil or not?
Not evil. I wish events worked this way by default. Can someone explain why an event with no subscribers is null?
You can always declare your events like this (not that i recommend it):
public event EventHandler<EventArgs> OnClicked = delegate { };
That way they have something assigned to them when you call them, so they don't throw a null pointer exception.
You can probably get rid of the delegate keyword in C# 3.0...
Don't forget to use [MethodImpl(MethodImplOptions.NoInlining)], else its possible that it isn't thread safe.
(Read that somewhere long ago, remembered it, googled and found http://blog.quantumbitdesigns.com/tag/events/ )
Coming from a java background this has always seemed odd to me. I think that no one listening to an event is perfectly valid. Especially when listeners are added and removed dynamically.
To me this seems one of C#'s gottchas that causes bugs when people don't know / forget to check for null every time.
Hiding this implementation detail seems a good plan as it's not helping readability to check for nulls every single time. I'm sure the MSFTs will say there's a performance gain in not constucting the event if no one is listening, but imho it is vastly outweighed by the pointless null pointer exceptions / reduction in readability in most business code.
I'd also add these two methods to the class:
public static void Raise(this EventHandler handler, object sender)
{
Raise(handler, sender, EventArgs.Empty);
}
public static void Raise<TA>(this EventHandler<TA> handler, object sender, TA args)
where TA : EventArgs
{
if (handler != null)
{
handler(sender, args);
}
}
Why would it be evil?
Its purpose is clear: It raises the MyButtonClicked event.
It does add a function call overhead, but in .NET it will either be optimized away or pretty fast anyway.
It is slightly trivial, but it fixes my biggest complaint with C#.
On the whole, I think it's a fantastic idea, and will probably steal it.
I wouldn't say it's evil, but I'm interested in how your extension method fits in with the
protected virtual OnSomeEvent(EventArgs e){ }
pattern and how it handles extensibility via inheritance. Does it presume all subclasses will handle the event instead of override a method?
Although I wouldn't describ it as evil, it still has a negative implication, as it adds unnecessary overhead:
When calling
myEvent.Raise(this, new EventArgs());
the object EventArgs is initialized in all situations, even if no-one subscribed to myEvent.
When using
if (myEvent!= null) {
myEvent(this, new EventArgs());
}
EventArgs is only initialized if someone subscribed to myEvent.
Throwing an exception when there are no handlers is not really preferable by the most. If it does not have an handlers it is better to be empty rather than null.