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.
Related
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.
Is there any point in wrapping event assignments in anonymous async functions?
Lets say this code is in some adapter class:
public event Action<int> someAction;
The following code is in some other class that sets the action:
Example 1:
_someAdapter.someAction += async (someParameter) =>
{
await HandleAction(someParamter);
};
In this case HandleAction has async Task return type.
Example 2:
_someAdapter.someAction += HandleAction;
In this case HandleAction has async void return type.
The same question applies to button click event handlers etc. I have seen examples of both and was wondering why this gets wrapped sometimes. From my testing there doesn't seem to be any difference.
I believe that using an anonymous handler wrapper you'll be able to let the C# Garbage Collector just "unhook" and destroy the handler on this (on example 1) when it is about to be destroyed.
Event handlers outside the this (it isn't the case in your example) would have special attention and wrap it looks a good choice.
If this will live a long time and there is some possibility of you have to hook that event again you should use another strategy to avoid memory leak like ones discussed on this question
The return types differences are related to exception handling and it's ok to use an async void on top-level methods and async event handlers.
I hope it helps.
In your example, there would be likely be no noticeable difference. This is more about coding standards and best practices. In general, it is not recommended that you create 'async void' functions, if you can avoid it. The purpose of that feature is to allow async code in functions that can't change their signature (like overrides). An 'async void' function has disadvantages like swallowing exceptions and being less composable.
If, for instance, you wanted to call HandleAction from another place/method (often this is the reason for using a named method instead of an anonymous function), you would not be able to await it unless it returns Task.
Also, if HandleAction threw an exception, you would not be able to catch it if you can't await it, so you better be sure it will handle all exceptions internally.
I won't recommend to use an anonymes delegate as an event handler. The reason is that it might come to cycling references and thus the garbage collector won't be able to free up memory - so called memory leak.
Especially in the Xamarin-world, where the managed garbage collector often won't know the real size of an object, developers should have an eye on memory and allocations their applications needs.
By avoiding anonymes delegates you are able to break the cycle simple by removing the event handler assignment.
I can't comment on your adapter handlers, but... seeing as you say "The same question applies to...", the answer might be the same as for button click event handlers, etc, which is (arguably the largest benefit of async in UI applications) - you get to perform expensive async operations in the handlers off the UI thread.
E.g.
_button.Click += async (...) =>
{
int answer = await ExpensiveHttpResultThatTakes10Seconds();
_answer.Text = answer.ToString();
};
If that wasn't async, the UI would freeze up for 10 seconds, not responding to clicks, keys, etc.
Because it is async, the UI remains responsive during those 10 seconds, as the await is non-blocking, processing UI events and even other event handlers.
I have a problem where the default delegate does not do enough in some cases. It needs a preamble and a postable. I'm just wondering whether it is better to call a triple delegate
CSELib.ELib eventLib = new CSELib.ELib();
eventLib.Bomb += BombCatcherStart;
eventLib.Bomb += eventLib.BombCatcher;
eventLib.Bomb += BombCatcherEnd;
...
eventLib.BombRaise();
or to call one delegate which then calls the three
void BombCatcherGroup(CSELib.Elib self)
{
BombCatcherStart(self);
self.BombCatcher(self);
BombCatcherEnd(self);
}
CSELib.ELib eventLib = new CSELib.ELib();
eventLib.Bomb += BombCatcherGroup;
...
eventLib.BombRaise();
It basically does the same thing but I just wondering as far as "best practice" is concerned, whether it is better to tell everyone up front as in the triple delegate or to hide it as in in the single delegate.
In the scenario where your operations form a logical chain there aren't really any pros to adding them as individual handlers to the same event - other than that those handlers can be removed down the track. If you don't need/want that, you're incurring the entirely avoidable (if negligible in most scenarios) overhead of additional delegate invocations and losing at least some of the ability to control execution flow. What happens if BombCatcher throws an exception? Easy to handle if all your operations are part of the same method definition; not so easy if you're dealing with separate delegates.
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.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is there a downside to adding an anonymous empty delegate on event declaration?
The following pattern is quite common when using event handlers (in C#):
public event Action handler;
…
// some method:
if(handler != null) handler();
Are there any downsides of assigning an empty delegate to this event? This would save the if !=null condition everywhere, where the event is fired. Of course, this only applies, when the we cannot guarantee that the event is always assigned a proper delegate.
public event Action handler;
…
// in constructor:
handler += ()=>{};
…
// some method:
handler();
Sure, there's a slight performance hit, but it makes the code much cleaner. What's the best practice in such a case? Any technical disadvantages?
Interesting idea, I've never thought of doing that. The way i do my custom events is i make a OnCustomEventName taking parameters for the event and just do the check in there for null. and call OnCustomEventName from the code wherever i want the event triggered from.
Avoids any performance hits and keeps the operational code cleaner than a 2-line if check every time you want the event fired.
That being said this isn't answering the question about technical disadvantages but more of a best practice when firing events.
example code for threadsafe "On" function.
private void OnCustomEventName()
{
DelegateName localhandler = CustomEventName;
if (localhandler != null)
localhandler();
}
Instead of adding an empty delegate in the constructor, you can wrap the handler in a function which first checks if the handler is null then calls it. The downside of this is if you have a lot of events, you will have a lot of functions that wrap each event.
private void HandlerWrapper()
{
Action localHandler = handler;
if (localHandler != null) handler();
}
I haven't really found any big downsides to do this and generally I prefer it over checking for null. The only issue I cant think of is that it might lead to annoying steps in the code when debugging (i.e.
having to step over the empty delegate whenever stepping into an event).
I think that performance isn't an issue - if application performance degenerates significantly by invoking events, the event should probably not have been there in the first place.