<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Sam Ng's Blog : Events</title><link>http://blogs.msdn.com/samng/archive/tags/Events/default.aspx</link><description>Tags: Events</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Virtual Events in C#</title><link>http://blogs.msdn.com/samng/archive/2007/11/26/virtual-events-in-c.aspx</link><pubDate>Tue, 27 Nov 2007 02:36:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6536977</guid><dc:creator>samng</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/samng/comments/6536977.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=6536977</wfw:commentRss><description>&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:6418de3a-9d69-478e-af2b-9b2eeb827c2c" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Events" rel="tag"&gt;Events&lt;/a&gt;&lt;/div&gt; &lt;p&gt;One of the things that the language designers considered when designing the C# language was the ability to notify external callers of certain events happening. To solve this problem, they (surprise surprise) introduced the event construct. &lt;/p&gt; &lt;p&gt;One of the oddities in the design however, comes in the form of virtual events. This is one of those design decisions that we recognize is something we would like to change, but as my colleague, Eric Lippert explains in a &lt;a href="http://blogs.msdn.com/ericlippert/archive/tags/Breaking+Changes/default.aspx"&gt;series of posts concerning breaking changes&lt;/a&gt;, we aren't able to fix everything that we would like to. &lt;/p&gt; &lt;h5&gt;How virtual events work&lt;/h5&gt; &lt;p&gt;So first off, lets quickly describe how virtual events work. Section 10.8.4 of the spec describes this for us:&lt;/p&gt; &lt;h6&gt;A &lt;strong&gt;virtual&lt;/strong&gt; event declaration specifies that the accessors of that event are virtual. The &lt;strong&gt;virtual &lt;/strong&gt;modifier applies to both accessors of an event.&lt;/h6&gt; &lt;h6&gt;The accessors of an inherited virtual event can be overridden in a derived class by including an event declaration that specifies an &lt;strong&gt;override&lt;/strong&gt; modifier. This is known as an &lt;em&gt;overriding event declaration&lt;/em&gt;. An overriding event declaration does not declare a new event. Instead, it simply specializes the implementations of the accessors of an existing virtual event.&lt;/h6&gt; &lt;p&gt;Notice that an overriding event does not declare a new event. Let's now quickly refresh field-like events and consider how they work in conjunction with virtual and overriding events. They are described in 10.8.1:&lt;/p&gt; &lt;h6&gt;Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event must not be &lt;strong&gt;abstract&lt;/strong&gt; or &lt;strong&gt;extern&lt;/strong&gt;, and must not explicitly include &lt;em&gt;event-accessor-declarations&lt;/em&gt;. Such an event can be used in any context that permits a field. The field contains a delegate (§15) which refers to the list of event handlers that have been added to the event. If no event handlers have been added, the field contains null.&lt;/h6&gt; &lt;p&gt;Declaring a virtual field-like event then, will cause the compiler to generate a delegate field to back the event, and virtual accessors for the event. Declaring an overriding field-like event will not cause the compiler to generate a new backing field for the overriding event in the case of field-like events, but will cause it to generate overriding accessors. &lt;/p&gt; &lt;h5&gt;A concrete example of virtual and overriding field-like events&lt;/h5&gt; &lt;p&gt;Now, consider some parent class P which declares a virtual event, and some derived class D which overrides it. First, note that we have four combinations:&lt;/p&gt; &lt;blockquote&gt; &lt;ol&gt; &lt;li&gt;P declares a field-like event, and D declares a field-like event  &lt;li&gt;P declares a field-like event, and D declares a user-defined event  &lt;li&gt;P declares a user-defined event, and D declares a field-like event  &lt;li&gt;P declares a user-defined event, and D declares a user-defined event&lt;/li&gt;&lt;/ol&gt;&lt;/blockquote&gt; &lt;p&gt;In case (1), P contains a delegate field backing the event, and two virtual accessors that add and remove from the delegate. D contains two overriding accessors, who add and remove from the delegate contained in P. &lt;strong&gt;Notice that for this to work, the delegate in P must be elevated from private to protected.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In case (2), P contains a delegate field and two accessors, and D contains the two user-defined overloaded accessors. &lt;strong&gt;D does not have access to the field contained in P.&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;In case (3), P contains the two virtual user-defined accessors, and D contains a delegate field, along with two overriding accessors that add and remove from the backing field.&lt;/p&gt; &lt;p&gt;In case (4), P contains the two virtual user-defined accessors, and D contains the two overriding user-defined accessors.&lt;/p&gt; &lt;p&gt;Here's the code for it:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;P
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case1_event;
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case2_event;
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case3_event
    {
        &lt;span style="color: rgb(0,0,255)"&gt;add&lt;/span&gt; { }
        &lt;span style="color: rgb(0,0,255)"&gt;remove&lt;/span&gt; { }
    }
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case4_event
    {
        &lt;span style="color: rgb(0,0,255)"&gt;add&lt;/span&gt; { }
        &lt;span style="color: rgb(0,0,255)"&gt;remove&lt;/span&gt; { }
    }
}

&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;D&lt;/span&gt; : &lt;span style="color: rgb(43,145,175)"&gt;P
&lt;/span&gt;{
    &lt;span style="color: rgb(0,128,0)"&gt;// D has access to P.case1_event's backing field.
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case1_event;

    &lt;span style="color: rgb(0,128,0)"&gt;// D does not have access to P.case2_event's backing field.
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case2_event
    {
        &lt;span style="color: rgb(0,0,255)"&gt;add&lt;/span&gt; { }
        &lt;span style="color: rgb(0,0,255)"&gt;remove&lt;/span&gt; { }
    }

    &lt;span style="color: rgb(0,128,0)"&gt;// D has a backing field generated for case3_event, which is private
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case3_event;

    &lt;span style="color: rgb(0,128,0)"&gt;// This is just the typical virtual/override pattern.
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; case4_event
    {
        &lt;span style="color: rgb(0,0,255)"&gt;add&lt;/span&gt; { }
        &lt;span style="color: rgb(0,0,255)"&gt;remove&lt;/span&gt; { }
    }
}
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;h5&gt;A bug in the compiler&lt;/h5&gt;
&lt;p&gt;The current C# compiler (in Visual Studio 2008 Beta2) has a bug when dealing with scenario (1) above. Consider the following scenario:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;P
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;virtual&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; myEvent;
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; parentEventCall()
    {
        myEvent(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;);
    }
}
&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;D&lt;/span&gt; : &lt;span style="color: rgb(43,145,175)"&gt;P
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;override&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;event&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt; myEvent;
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; derivedEventCall()
    {
        myEvent(&lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;null&lt;/span&gt;);
    }
}

&lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Program
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Main(&lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt;[] args)
    {
        &lt;span style="color: rgb(0,128,0)"&gt;// Create an instance of D, and create a P reference to it.
&lt;/span&gt;        &lt;span style="color: rgb(43,145,175)"&gt;D&lt;/span&gt; derived = &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;D&lt;/span&gt;();
        &lt;span style="color: rgb(43,145,175)"&gt;P&lt;/span&gt; parent = derived;

        &lt;span style="color: rgb(0,128,0)"&gt;// Hook a handler up through the derived and parent references.
&lt;/span&gt;        derived.myEvent += &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt;(derivedHandler);
        parent.myEvent += &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;EventHandler&lt;/span&gt;(parentHandler);

        &lt;span style="color: rgb(0,128,0)"&gt;// Fire both events.
&lt;/span&gt;        derived.derivedEventCall();
        parent.parentEventCall();

    }
    &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; parentHandler(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43,145,175)"&gt;EventArgs&lt;/span&gt; e)
    {
        &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"parent handler"&lt;/span&gt;);
    }

    &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; derivedHandler(&lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; sender, &lt;span style="color: rgb(43,145,175)"&gt;EventArgs&lt;/span&gt; e)
    {
        &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(&lt;span style="color: rgb(163,21,21)"&gt;"derived handler"&lt;/span&gt;);
    }
}&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;Now, we would expect this code to output the sequence of derived/parent/derived/parent handlers being fired, because in this scenario, we should have one backing field for both the virtual event and the overriding one, so both of the trigger calls should act upon the same event, and both of the handlers should be hooked onto the same event.&lt;/p&gt;
&lt;p&gt;However, if you go ahead and paste this code into Visual Studio, compile it, then run it, you'll get a NullReferenceException being thrown. Debugging it will show us two thing:&lt;/p&gt;
&lt;p&gt;Firstly, the compiler does not generate a protected backing field on the parent class P. Instead, it generates two private backing fields - one in P and one in D.&lt;/p&gt;
&lt;p&gt;Secondly, when we execute both handler hookups, we'll see that it is the derived delegate field that gets both of the handlers hooked up to it.&lt;/p&gt;
&lt;p&gt;When we step into parentEventCall then, we'll notice that the this pointer is of type P, and that the only visible backing field is P.myEvent, which is null. Attempting to trigger the delegate then throws us the NullReferenceException, as expected.&lt;/p&gt;
&lt;h5&gt;The work-around&lt;/h5&gt;
&lt;p&gt;The simple work-around for the issue is to use a virtual method for triggering the event as well. An easy to remember rule of thumb is that if you have a virtual event, have a virtual triggering method. If you override a virtual event, override its trigger method as well.&lt;/p&gt;
&lt;h5&gt;A quick argument for not-fixing this issue&lt;/h5&gt;
&lt;p&gt;There are two main reasons that prompted us to choose to not fix this issue. &lt;/p&gt;
&lt;p&gt;The first is the common practice for declaring event trigger methods. Whenever you write a trigger method, you must do a null check - if you don't and someone calls your trigger method without ever adding a handler, you'll get a NullreferenceException. This means that anyone applying good coding practices will already be safeguarded from this erroneous exception being thrown.&lt;/p&gt;
&lt;p&gt;However, fixing this issue will be a breaking change. Code that used to never execute because the backing field in the parent class was always null will now execute because the backing field is the same in both the parent and derived classes, and will have a value once a handler is added. This is undesirable.&lt;/p&gt;
&lt;p&gt;Secondly, there really is no need to be in this scenario in the first place. Using a virtual field-like event in the parent class and not changing any of its behavior in the overriding derived class is not necessary. You can simply omit the override in the derived class to get the desired behavior.&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f26%2fvirtual-events-in-c.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f26%2fvirtual-events-in-c.aspx" border="0"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6536977" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/samng/archive/tags/Events/default.aspx">Events</category></item></channel></rss>