Is there a downside to adding an anonymous empty delegate on event declaration?
The only downside is a very slight performance penalty as you are calling extra empty delegate. Other than that there is no maintenance penalty or other drawback.
Is it a good practice to define an empty delegate body for a event?
I've certainly found it useful, yes. There will be a tiny, tiny performance cost - but the benefit in readability for not having to perform the nullity test makes it worth it IMO.
It's worth pointing out that this is one of the few times when it's good to use an anonymous method rather than a lambda expression - otherwise you have to name the parameters that you're going to ignore, like this:
public event EventHandler<LoadEventArgs> LoadedData = (sender, args) => {};
I don't like having to name things I'm not intending to use :)
What is the point of assigning an empty delegate to an event?
Normally, when you are to raise an event, you have to check for null values, meaning, no event handlers attached. With this approach, you can skip this check, because the event will always have an empty handler.
Event declaration with assignment to empty delegate
UPDATE: in modern versions of C#, the recommended pattern to use is to leave it as null and use the ?.
operator:
event Action<Foo> foo; // leave it as null as the default
// ...
foo?.(new Foo());
In older versions of C#, the reason for this pattern could be that the default value of an event
field is null
. This requires the use of a null-check every-time you want to raise the event - calling foo()
on an uninitialised event
field would result in a NullReferenceException
. It's more convenient to just give it a sensible default value like a no-op, that way you can raise the event directly without having to use a wrapper method or anything.
Will an empty delegate eat up memory?
Scratch the previous answer (kept below for posterity). It depends on the implementation of the compiler, but under the current MS C# 3.0 compiler, this actually only creates a single instance which is reused for every instance. It's able to do that because delegates are immutable and that delegate doesn't require any information from the instance.
I don't know whether this was the case with C# 2.0 though. You can decompile your code and see whether the IL actually uses a cached field or not. Using the answer below is a safe way to guarantee you'll only create one instance though.
Original answer:
Yes, it creates an instance of a delegate. That will take some memory. You could reduce that though:
public static class EventHandlers
{
public static readonly EventHandler Empty = delegate {};
}
public sealed class FtpManager
{
public event EventHandler LoggingIn = EventHandlers.Empty;
}
At that point there'll just be the one instance, and you can refer to it from anywhere. The downside is that other classes could then unsubscribe using the same handler. If you trust the rest of your codebase not to do that, this is probably the best bet from a memory point of view.
Can an anonymous delegate unsubscribe itself from an event once it has been fired?
You can save an instance of the delegate before subscribing to the event:
public void QueueNotAvailable()
{
SomeHandler handler = null;
handler = (s,e) {
// ...
StateChanged -= handler;
};
StateChanged += handler;
}
I believe this should do it... I had to put the initial handler = null
in there otherwise you get 'Use of unassigned local variable' compilation errors, but I think it's actually benign.
Is it necessary have someone registered to an event before you can raise it?
yes, an event with no-one registered on it is null. The standard way of firing events is:
event EventHandler MyEvent;
private void FireMyEvent(EventArgs e) {
var handler = MyEvent;
if (handler != null)
handler(this, e);
}
Eric Lippert has written a fantastic article on why this pattern is the 'correct' way of firing events
Related Topics
Get the Ip Address of the Remote Host
How to Get All Classes Within a Namespace
Example Ajax Call Back to an ASP.NET Core Razor Page
Using Side-By-Side Assemblies to Load the X64 or X32 Version of a Dll
What Does the Tilde Before a Function Name Mean in C#
How to Return Multiple Result Sets with SQLcommand
Creating a Comma Separated List from Ilist<String> or Ienumerable<String>
Does Xaml Have a Conditional Compiler Directive for Debug Mode
C# Use System.Type as Generic Parameter
Converting String to Double in C#
Turn a Simple C# Dll into a Com Interop Component
Why Does Boolean.Tostring Output "True" and Not "True"
Does C# Optimize the Concatenation of String Literals
Return View as String in .Net Core
How to Force All Referenced Assemblies to Be Loaded into the App Domain
Write File from Assembly Resource Stream to Disk