From this question (and others) there's this example of snapshoting the event handler value before invoking:
var tmp = _myEventHandler;
if(tmp != null) {
tmp(sender, args);
}
However, if I pass in the event handler and args into a function does this do the same thing?
protected void Invoke(MyEventHandler handler, MyEventArgs args)
{
if (handler != null)
handler(this, args);
}
I would say yes, but after thinking about this I don't know if it is the same - like could an optimization process inline this function and remove the snapshot variable?
It indeed does the same thing. The code is simply checking that the event handler is non-null and hence available for raising. This code is no different for a field / parameter / local. The C# compiler or JITer cannot inline this in such a way that the temporary is removed because it would change the semantics of the program.
The race condition is explained in your other links, such as Marc Gravell's answer.
As #JaredPar points out, your code effectively does the same thing. However, it violates the standard event conventions for .NET, which recommend the following:
protected virtual void OnAlarmRaised(AlarmRaisedEventArgs e)
You are free to violate the pattern, but doing so goes against the grain for minimal (if any) benefit.
Related
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.
This question already has answers here:
event Action<> vs event EventHandler<>
(7 answers)
Closed 9 years ago.
What speaks against using the delegates System.Action or System.Func as EventDelegates instead of the classic EventHandler pattern. Will I therefore run into problems?
private bool disposed;
public event Action<IUnitOfWork, IContext> Disposing;
public void Dispose()
{
if (this.disposed)
{
return;
}
if (null != this.Disposing)
{
this.Disposing(this, this.AttachedContext);
}
this.disposed = true;
}
Usage:
unitOfWorkInstance.Disposing += (u, c) => c.Rollback(u); // in my opinion more readable than
unitOfWorkInstance.Disposing += (sender, args) => args.AttachedContext.Rollback(sender as IUnitOfWork);
Well, the code you've given there isn't thread-safe - someone could unsubscribe from the eventhandler after your nullity test and before your call this.Disposing.
But in general, it should work just fine. The downside is that by not following the EventHandler convention, you're slightly more limited in terms of what can subscribe.
For example, suppose you have a very general event handler method:
public void LogEvent(object sender, EventArgs e)
{
Console.WriteLine("Event raised");
}
You can use this to subscribe to any event following the normal convention - but not with
your event.
This is a pretty minor downside though. I guess a potentially bigger one is that it may confuse other developers who are expecting to see a conventional event signature.
EDIT: I've just remembered that some other libraries may expect the conventional event signature - Reactive Extensions does, for example. IIRC, it's not impossible to subscribe to other events, just a bit harder.
From a "does-the-code-work" perspective, I would say it is perfectly OK to use these delegate types for events.
The problem with doing this, is that you are not following the common pattern for events, where the delegate is EventHandler<TEventArgs>, and TEventArgs is a custom type that contains the parameters for the event. The benefits of following this pattern include:
Code readability
Not having to change event subscribers if you need to add a parameter to the events (because you will just add it to your custom event arguments class).
In general:
There is no problem with using Action as your event handler. It is supported by the language, so use it :)
The only case I can think of is code that tries to find your events via reflections. But if that code couldn't handle any delegate as an event type, I'd say their code was buggy, not yours.
Your specific example:
The problem with the pattern you are using is that you shouldn't really be using the object while in the Dispose method. It could be safe sometimes, but would be easy to get wrong.
For example, if the Dispose method disposed resources before raising the event, then the object would be in an unusable state.
This could be hard (without comments and strong code reviews) for a maintenance programmer to get right when editing your Dispose method.
Why would a 'public event EventHandler cccc' be null?
I have a class that's
public class Builder
{
public event EventHandler StartedWorking;
public Builder()
{
// Constructor does some stuff
}
public void Start()
{
StartedWorking(this, eventargobject); //StartedWorking is null --
}
}
This seems straightforward and something I do all the time? Am I missing something obvious or is there something that could cause this?
EDIT:
Does this mean that if I fire an event that is not subscribed to in a client class I have to check that it is not null?
EDIT-2:
I guess I'd never had events that were never not subscribed to and hence never ran into this --
You learn something new every day
Sorry about the seemingly stupid question....
The event handler will be null unless somebody has subscribed to the event. As soon as a delegate is subscribed to the event, it will no longer be null.
This is why it's always suggested to use the following form for raising events:
public void Start()
{
var handler = this.StartedWorking;
if (handler != null)
{
handler(this, eventArgObject);
}
}
This protects you from a null exception if there has been no subscribers.
As others have already said, it's null because there are no subscribers.
To answer your edit: Yes, you should always check an event for null before triggering it. However, if you just do a plain if(StartedWorking != null){...} you risk a race condition, because it's possible for a subscriber to unsubscribe after the null check but before you trigger the event. Because of this, you should always use this pattern when checking events for null:
protected void OnStartedWorking()
{
EventHandler localEvent = StartedWorking
if(localEvent != null)
{
localEvent(this, EventArgs.Empty);
}
}
This prevents the race condition by taking a copy of the event first so the subscribe list is fixed at the point of copying.
There's more infomration about publishing events on MSDN: How to Publish Events that Conform to .NET Framework Guidelines
(This works because in .net the MultiCastDelegate class in imutable, so any attempt to change the subscriber list on the event won't effect the copy you have made)
If you haven't hooked any event subscribers up to your StartedWorking event, then it will be null. That is how .NET events works.
This article, among other things, demonstrates that you should check for null before invoking an event. This other question and answer demonstrates how you can create events in a way that avoids the null check (basically by adding an empty handler always).
Don't you need to assign a function ?
StartedWorking += new EventHandler(afunction);
void afunction(object sender, EventArgs e)
{
DoSomething();
}
-- If I define an event with an inital empty delegate I don't need to check for null
class MyClass
{
public event EventHandler<MyEventArgs> MyEvent = delegate { };
void SomeMethod()
{
...
MyEvent(); // No need to check for null
...
}
}
-- Otherwise I need to check for null
class MyClass
{
public event EventHandler<MyEventArgs> MyEvent;
void SomeMethod()
{
...
if (MyEvent != null) // No need to check for null
MyEvent();
...
}
}
What's the difference between these? In what cases one is better than another?
Thanks
The upvoted answer is dramatically wrong, I have to post an answer. Somebody is wrong on the Internet, can't come to bed just yet.
It is convenient but it doesn't come for free. The compiler has to generate a class for the anonymous method and the JIT compiler has to generate code for it. And that code always executes when you raise the event, whether or not a client has subscribed an event handler. The null check code also always executes, but that takes a lot less code and time.
This isn't a lot of code and a lot of time. The null check takes 2 machine code instructions and should execute in a single CPU cycle. The anonymous delegate takes about an order of magnitude more but that's still not a lot on a modern machine. Personally, I'm too old to be wasteful like that, two invariably is my choice.
Not in the least because that's the standard pattern, everybody recognizes it.
First one is applicable solution, but it has very very little performance penalty to call extra empty delegate.
Second solution is not thread safe (if it matters for you, of cause).
You should use following:
var handler = MyEvent;
if (handler != null )
handler(this, new MyEventArgs());
At our company we wrote an extension method which hooks onto most events, and checks if it's null before invoking.
We reduced this:
var handler = MyEvent;
if (handler != null)
{
handler(...);
}
to
MyEvent.SafeTrigger(...);
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.