Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I've written this up in a fair amount of detail in <a href="http://pobox.com/~skeet/csharp/events.html" rel="noreferrer">an article</a>, but here's the summary, assuming you're reasonably happy with <a href="http://msdn.microsoft.com/en-us/library/ms173171.aspx" rel="noreferrer">delegates</a> themselves:</p> <ul> <li>An event is just an "add" method and a "remove" method, in the same way that a property is really just a "get" method and a "set" method. (In fact, the CLI allows a "raise/fire" method as well, but C# never generates this.) Metadata describes the event with references to the methods.</li> <li>When you declare a <em><a href="http://msdn.microsoft.com/en-us/library/aa664455.aspx" rel="noreferrer">field-like event</a></em> (like your ElementAddedEvent) the compiler generates the methods <em>and a private field</em> (of the same type as the delegate). Within the class, when you refer to ElementAddedEvent you're referring to the field. Outside the class, you're referring to the field.</li> <li>When anyone subscribes to an event (with the += operator) that calls the add method. When they unsubscribe (with the -= operator) that calls the remove.</li> <li><p>For field-like events, there's some synchronization but otherwise the add/remove just call Delegate.<a href="http://msdn.microsoft.com/en-us/library/system.delegate.combine.aspx" rel="noreferrer">Combine</a>/<a href="http://msdn.microsoft.com/en-us/library/system.delegate.remove.aspx" rel="noreferrer">Remove</a> to change the value of the auto-generated field. Both of these operations assign to the backing field - remember that delegates are immutable. In other words, the autogenerated code is very much like this:</p> <pre><code>// Backing field // The underscores just make it simpler to see what's going on here. // In the rest of your source code for this class, if you refer to // ElementAddedEvent, you're really referring to this field. private EventHandler&lt;EventArgs&gt; __ElementAddedEvent; // Actual event public EventHandler&lt;EventArgs&gt; ElementAddedEvent { add { lock(this) { // Equivalent to __ElementAddedEvent += value; __ElementAddedEvent = Delegate.Combine(__ElementAddedEvent, value); } } remove { lock(this) { // Equivalent to __ElementAddedEvent -= value; __ElementAddedEvent = Delegate.Remove(__ElementAddedEvent, value); } } } </code></pre></li> <li><p>The initial value of the generated field in your case is <code>null</code> - and it will always become <code>null</code> again if all subscribers are removed, as that is the behaviour of Delegate.Remove.</p></li> <li><p>If you want a "no-op" handler to subscribe to your event, so as to avoid the nullity check, you can do:</p> <pre><code>public EventHandler&lt;EventArgs&gt; ElementAddedEvent = delegate {}; </code></pre> <p>The <code>delegate {}</code> is just an anonymous method which doesn't care about its parameters and does nothing.</p></li> </ul> <p>If there's anything that's still unclear, please ask and I'll try to help!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload