<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.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>Peter Ritchie's MVP Blog : C# 3.0, .NET 3.5</title><link>http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/.NET+3.5/default.aspx</link><description>Tags: C# 3.0, .NET 3.5</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Deep Dive on Closure Pitfalls</title><link>http://msmvps.com/blogs/peterritchie/archive/2010/11/03/deep-dive-on-closure-pitfals.aspx</link><pubDate>Wed, 03 Nov 2010 13:23:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1781490</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1781490</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2010/11/03/deep-dive-on-closure-pitfals.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve &lt;a href="http://msmvps.com/blogs/peterritchie/archive/2008/10/27/closure-tip.aspx"&gt;blogged about closures in C# and their pitfalls&lt;/a&gt; before.&amp;nbsp; I keep seeing problems with closures--more now that lambdas expressions and statements (&amp;quot;lambdas&amp;quot;)&amp;nbsp;are becoming more widespread--even with experienced developers. So, I&amp;#39;d thought i&amp;#39;d post about some of the details surrounding where the C# compiler generates closures in the hopes that people will recognize more where they write code that creates a closure and its context.&lt;/p&gt;
&lt;p&gt;The C# language spec does not refer specifically to &amp;quot;closures&amp;quot;, with regard to capturing state for anonymous methods (including lambdas)--it refers to &amp;quot;outer variables&amp;quot; and &amp;quot;captured outer variables&amp;quot;.&amp;nbsp; The captured outer variables for a specific anonymous method are the &amp;quot;closure&amp;quot;.&lt;/p&gt;
&lt;p&gt;The compiler captures the state of variables within the local scope of the anonymous method in a compiler-generated class.&amp;nbsp; The compiler effectively also captures the declaration scope of the state within the closure.&amp;nbsp; If a variable is declared outside the local scope, that is echoed in the use of that closure.&amp;nbsp; If the variable is declared within the local scope, that is captured in use of the closure.&amp;nbsp; So, an anonymous method that uses state (a variable) declared outside the local scope of the anonymous method, the compiler will generate a closure use that closure so that variable is only instantiated once.&amp;nbsp; For example:&amp;nbsp;&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:#2b91af;"&gt;ICollection&lt;/span&gt;&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;&amp;nbsp;Funcs&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;List&lt;/span&gt;&amp;lt;&lt;span style="COLOR:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;();&amp;nbsp;&lt;br /&gt;	&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;[]&amp;nbsp;texts&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;[]&amp;nbsp;{&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;one&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;two&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;three&amp;quot;&lt;/span&gt;&amp;nbsp;};&lt;br /&gt;	&lt;span style="COLOR:blue;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="COLOR:#2b91af;"&gt;String&lt;/span&gt;&amp;nbsp;text&amp;nbsp;&lt;span style="COLOR:blue;"&gt;in&lt;/span&gt;&amp;nbsp;texts)&lt;br /&gt;	{&lt;br /&gt;&lt;span style="background-color:#ffff99;"&gt;		Funcs.Add(&lt;span style="color:blue;"&gt;delegate&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;text;&amp;nbsp;});&lt;br /&gt;&lt;/span&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;We have an anonymous method used within the local scope of the body of the foreach loop.&amp;nbsp; The anonymous method uses the &lt;span style="font-family:courier new,courier;"&gt;text&lt;/span&gt; variable declared outside the scope of the foreach loop.&amp;nbsp; The compiler generates a class to contain the state&amp;nbsp;and the code that uses that state&amp;nbsp;(i.e. the anonymous method)--otherwise the highlighted code--and make use of that generated class.&amp;nbsp;&amp;nbsp;For example:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="color:blue;"&gt;&lt;span style="color:#2b91af;"&gt;Closure &lt;/span&gt;&lt;/span&gt;closure&amp;nbsp;=&amp;nbsp;&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Closure&lt;/span&gt;();&lt;br /&gt;	&lt;span style="color:blue;"&gt;for&lt;/span&gt;&amp;nbsp;(&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;texts.Length;&amp;nbsp;++i)&lt;br /&gt;	{&lt;br /&gt;		closure.text&amp;nbsp;=&amp;nbsp;texts[i];&lt;br /&gt;		Funcs.Add(&lt;span style="color:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;gt;(closure.Func));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;The compiler-generated class may look something like this:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="color:blue;"&gt;internal&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Closure&lt;/span&gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;nbsp;text;&lt;br /&gt;		&lt;span style="color:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="color:blue;"&gt;string&lt;/span&gt;&amp;nbsp;Func()&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;text;&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;The compiler instantiates that&amp;nbsp;class outside the generated for loop (because there is no &amp;quot;foreach&amp;quot; loop in .NET&amp;nbsp;IL--what we see here for generated code is a C# view of IL)&amp;nbsp;to match the single declaration of the &lt;span style="font-family:courier new,courier;"&gt;text&lt;/span&gt; variable (as the body of the foreach loop sees it).&amp;nbsp; So, as we can tell from this code, each of these &lt;span style="font-family:courier new,courier;"&gt;Func&lt;/span&gt; delegates are accessing the same variable.&amp;nbsp; So, if we invoked each of those delegate, they would all return &amp;quot;three&amp;quot;.&amp;nbsp; While the code &lt;em&gt;looks&lt;/em&gt; like each &lt;span style="font-family:courier new,courier;"&gt;Func&lt;/span&gt; delegate is dealing with a different value (&amp;quot;one&amp;quot;, then &amp;quot;two&amp;quot;, then &amp;quot;three&amp;quot;); it&amp;#39;s not and you&amp;#39;ve probably got a logic error with this code.&lt;/p&gt;
&lt;p&gt;So, as I pointed out in a previous post, we get around the problem by bringing the value from the outer scope into the inner scope of the anonymous method.&amp;nbsp; For example:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="color:blue;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="color:#2b91af;"&gt;String&lt;/span&gt;&amp;nbsp;text&amp;nbsp;&lt;span style="color:blue;"&gt;in&lt;/span&gt;&amp;nbsp;texts)&lt;br /&gt;	{&lt;br /&gt;&lt;span style="background-color:#ffff99;"&gt;		&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;temp&amp;nbsp;=&amp;nbsp;text;&lt;br /&gt;		Funcs.Add(&lt;span style="color:blue;"&gt;delegate&lt;/span&gt;&amp;nbsp;{&amp;nbsp;&lt;span style="color:blue;"&gt;return&lt;/span&gt;&amp;nbsp;temp;&amp;nbsp;});&lt;br /&gt;&lt;/span&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;Now, the compiler needs to generate a class to model this local scope--or the highlighted code.&amp;nbsp; This local scope includes the creation of an object and assigning it a specific value.&amp;nbsp; So, what the compiler generates now would be similar to the following:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:blue;"&gt;for&lt;/span&gt;&amp;nbsp;(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;texts.Length;&amp;nbsp;++i)&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;&amp;nbsp;closure&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;();&lt;br /&gt;		closure.temp&amp;nbsp;=&amp;nbsp;texts[i];&lt;br /&gt;		Funcs.Add(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt;(closure.Func));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;With a closure class similar to:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:blue;"&gt;private&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;class&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;nbsp;temp;&lt;br /&gt;		&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;nbsp;Func()&lt;br /&gt;		{&lt;br /&gt;			&lt;span style="COLOR:blue;"&gt;return&lt;/span&gt;&amp;nbsp;temp;&lt;br /&gt;		}&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;As we can see here, the compiler is now&amp;nbsp;instantiating a&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt; class once for each iteration of the loop, assigning a specific value to the &lt;span style="font-family:courier new,courier;"&gt;temp&lt;/span&gt; field, then passing a delegate to the &lt;span style="font-family:courier new,courier;"&gt;Func&lt;/span&gt; instance method to a new&lt;span style="font-family:courier new,courier;"&gt; Func&amp;lt;T&amp;gt;&lt;/span&gt; delegate.&amp;nbsp; Now, if we invoke each of our Func delegates we get what we expect &amp;quot;one&amp;quot;, then &amp;quot;two&amp;quot;, then &amp;quot;three&amp;quot;.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve specifically chosen deferred execution in these examples to separate parallel processing and what&amp;#39;s going on.&amp;nbsp; The same issue occurs when we use anonymous delegates with multiple threads.&amp;nbsp;&amp;nbsp;&amp;nbsp;For example:&amp;nbsp;&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:blue;"&gt;var&lt;/span&gt;&amp;nbsp;texts&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;[]&amp;nbsp;{&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;one&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;two&amp;quot;&lt;/span&gt;,&amp;nbsp;&lt;span style="COLOR:#a31515;"&gt;&amp;quot;three&amp;quot;&lt;/span&gt;&amp;nbsp;};&lt;br /&gt;	&lt;span style="COLOR:blue;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="COLOR:blue;"&gt;var&lt;/span&gt;&amp;nbsp;text&amp;nbsp;&lt;span style="COLOR:blue;"&gt;in&lt;/span&gt;&amp;nbsp;texts)&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="COLOR:#2b91af;"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(v&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Trace&lt;/span&gt;.WriteLine(text));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;This anonymous method (as a lambda) would generate code similar to:&lt;/p&gt;
&lt;pre style="FONT-FAMILY:consolas;"&gt;&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;&amp;nbsp;closure&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;();&lt;br /&gt;	&lt;span style="COLOR:blue;"&gt;for&lt;/span&gt;&amp;nbsp;(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;texts.Length;&amp;nbsp;++i)&lt;br /&gt;	{&lt;br /&gt;		closure.text&amp;nbsp;=&amp;nbsp;texts[i];&lt;br /&gt;		&lt;span style="COLOR:#2b91af;"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;WaitCallBack(closure.WaitCallback));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;As you can see, each thread is actually dealing with a single variable (Closure.text). At worst case&amp;nbsp;when each thread runs, it outputs &amp;quot;three&amp;quot;--otherwise it&amp;#39;s undefined what you&amp;#39;ll see.&amp;nbsp; We fix that the same way we did previously by adding a variable into the local scope:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;	&lt;span style="color:blue;"&gt;foreach&lt;/span&gt;&amp;nbsp;(&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;text&amp;nbsp;&lt;span style="color:blue;"&gt;in&lt;/span&gt;&amp;nbsp;texts)&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="color:blue;"&gt;var&lt;/span&gt;&amp;nbsp;temp&amp;nbsp;=&amp;nbsp;text;&lt;br /&gt;		&lt;span style="color:#2b91af;"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(v&amp;nbsp;=&amp;gt;&amp;nbsp;&lt;span style="color:#2b91af;"&gt;Trace&lt;/span&gt;.WriteLine(temp));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;This then generates something like this:&lt;/p&gt;
&lt;pre style="font-family:consolas;"&gt;&lt;pre style="FONT-FAMILY:consolas;"&gt;	&lt;span style="COLOR:blue;"&gt;for&lt;/span&gt;&amp;nbsp;(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;texts.Length;&amp;nbsp;++i)&lt;br /&gt;	{&lt;br /&gt;		&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;&amp;nbsp;closure&amp;nbsp;=&amp;nbsp;&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt;();&lt;br /&gt;		closure.temp&amp;nbsp;=&amp;nbsp;texts[i];&lt;br /&gt;		&lt;span style="COLOR:#2b91af;"&gt;ThreadPool&lt;/span&gt;.QueueUserWorkItem(&lt;span style="COLOR:blue;"&gt;new&lt;/span&gt;&amp;nbsp;&lt;span style="COLOR:#2b91af;"&gt;WaitCallback&lt;/span&gt;(closure.WaitCallback));&lt;br /&gt;	}&lt;br /&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;This means each thread is operating on an independent variable (the &lt;span style="font-family:courier new,courier;"&gt;Closure.temp&lt;/span&gt; field of each instance of &lt;span style="COLOR:#2b91af;"&gt;Closure&lt;/span&gt; that was instantiated).&lt;/p&gt;
&lt;p&gt;I hope this makes it more clear what the compiler is doing when you use anonymous methods (including Lambdas).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2010%2f11%2f03%2fdeep-dive-on-closure-pitfals.aspx"&gt;&lt;img src="http://dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%253a%252f%252fmsmvps.com%252fblogs%252fpeterritchie%252farchive%252f2010%252f11%252f03%252fdeep-dive-on-closure-pitfals.aspx" alt="kick it on DotNetKicks.com" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1781490" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+2.0/default.aspx">.NET 2.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.x/default.aspx">.NET 3.x</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/DevCenterPost/default.aspx">DevCenterPost</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+4/default.aspx">C# 4</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development+Guidance/default.aspx">Software Development Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+4.0/default.aspx">.NET 4.0</category></item><item><title>DevTeach 2009 Vancouver</title><link>http://msmvps.com/blogs/peterritchie/archive/2009/03/26/devteach-2009-vancouver.aspx</link><pubDate>Thu, 26 Mar 2009 16:33:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1681658</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1681658</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2009/03/26/devteach-2009-vancouver.aspx#comments</comments><description>&lt;p&gt;The schedule for DevTeach 2009 Vancouver has been announced (&lt;a href="http://www.devteach.com/" title="http://www.devteach.com/"&gt;http://www.devteach.com/&lt;/a&gt;).&amp;nbsp; There&amp;rsquo;s lots of great software development sessions from some of the leaders in our industry.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re planning on improving yourself, this is the conference to go to.&amp;nbsp; Not only can you attend excellent sessions; but you can hob-knob with the presenters and pick their brains.&lt;/p&gt;
&lt;p&gt;If you have a friend or co-worker who&amp;rsquo;s interested, there&amp;rsquo;s a limited-time two-for-one offer for an even better price: &lt;a href="http://www.devteach.com/Register.aspx" title="http://www.devteach.com/Register.aspx"&gt;http://www.devteach.com/Register.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2009%2f03%2f26%2fdevteach-2009-vancouver.aspx"&gt;&lt;img border="0" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2009%2f03%2f26%2fdevteach-2009-vancouver.aspx" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1681658" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development/default.aspx">Software Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Visual+Studio+2005/default.aspx">Visual Studio 2005</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+2.0/default.aspx">.NET 2.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.x/default.aspx">.NET 3.x</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/DevTeach/default.aspx">DevTeach</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/DDD/default.aspx">DDD</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development+Practices/default.aspx">Software Development Practices</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development+Guidance/default.aspx">Software Development Guidance</category></item><item><title>Nested Types</title><link>http://msmvps.com/blogs/peterritchie/archive/2008/07/15/nested-types.aspx</link><pubDate>Tue, 15 Jul 2008 14:47:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1640904</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1640904</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2008/07/15/nested-types.aspx#comments</comments><description>&lt;p&gt;Recently &lt;a href="http://www.michaelfeathers.com/"&gt;Michael Features&lt;/a&gt; &lt;a href="http://michaelfeathers.typepad.com/michael_feathers_blog/2008/06/are-nested-clas.html"&gt;blogged about nested types&lt;/a&gt;.&amp;nbsp; The title was almost &amp;quot;nested types considered harmful&amp;quot;.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t agree.&amp;nbsp; I don&amp;#39;t agree that they&amp;#39;re any more harmful than any other C# construct (except goto...).&amp;nbsp; Nested types are like anything else in our tool-belt: they have a time and place and can be abused.&lt;/p&gt;
&lt;p&gt;But, when to use them?&amp;nbsp; Well, for the most part I agree with Michael, you should avoid them. But, there are times when they&amp;#39;re simply the best solution in a given set of circumstances.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s look at asynchronous programming model (APM) in .NET.&lt;/p&gt;
&lt;div style="BORDER-RIGHT:black 1px solid;BORDER-TOP:black 1px solid;FONT-SIZE:10pt;BACKGROUND:white;BORDER-LEFT:black 1px solid;COLOR:black;BORDER-BOTTOM:black 1px solid;FONT-FAMILY:Courier New;"&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Paraphrased from MSDN&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&lt;span style="color:#008000;"&gt;        // Accept one client connection asynchronously.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DoBeginAcceptTcpClient(&lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; listener)&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Start to listen for connections from a client.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Trace&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Waiting for a connection...&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Accept the connection. &lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// BeginAcceptSocket() creates the accepted socket.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; listener.BeginAcceptTcpClient(&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DoAcceptTcpClientCallback,&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; listener);&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Process the client connection.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DoAcceptTcpClientCallback(&lt;span style="color:#2b91af;"&gt;IAsyncResult&lt;/span&gt; ar)&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Get the listener that handles the client request.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt; listener = (&lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt;)ar.AsyncState;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// End the operation and display the received data on &lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// the console.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;TcpClient&lt;/span&gt; client = listener.EndAcceptTcpClient(ar);&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// TODO: do something with client.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Process the connection here. (Add the client to a&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// server table, read data, etc.)&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Trace&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Client connected completed&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;pre style="BACKGROUND:cornsilk;MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;In this simple scenario we are getting by with a state of simply a TcpListener object.&amp;nbsp; In a more complex scenario, you&amp;#39;ll likely also want a connection-specific queue, some sort of information about what to do after a connection, etc.&amp;nbsp; While you can use existing types of have several collection instance fields to keep track of each of these things; you then have to introduce synchronization of those collections, managing the content of those collections, etc.--it&amp;#39;s much easier and safer to send that information on the stack.&amp;nbsp; One method I&amp;#39;ve tried is simply passing an Object collection as the state; but that quickly becomes hard to manage because of the lack of type-safety on the elements in the array (if I remove an element and replace it with another type, the compile can&amp;#39;t know and I&amp;#39;ll get a run-time error instead of a compile-time error).&amp;nbsp; To get type safety I generally introduce a new type to aggregate all the types I need in this asynchronous callback.&amp;nbsp; While this new type *could* be reusable by other classes; it likely isn&amp;#39;t and I don&amp;#39;t want to then be bound that that explicit contract I&amp;#39;ve signed by making the types publicly available.&amp;nbsp; The only option of not making them publicly available is as private nested types.&amp;nbsp; For example: &lt;/p&gt;

&lt;div style="font-size:10pt;background:white;color:black;font-family:Courier New;border:black 1px solid;"&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;AcceptTcpClientParameters&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;CommandQueue&lt;/span&gt; CommandQueue { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;Command&lt;/span&gt; NextCommand { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt; TcpListener { &lt;span style="color:#0000ff;"&gt;get&lt;/span&gt;; &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;set&lt;/span&gt;; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AcceptTcpClientParameters(&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; commandQueue, &lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; nextCommand, &lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt; tcpListener)&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; CommandQueue = commandQueue;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; NextCommand = nextCommand;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; TcpListener = tcpListener;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Accept one client connection asynchronously.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DoBeginAcceptTcpClient(&lt;span style="color:#2b91af;"&gt;TcpListener&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; listener, &lt;span style="color:#2b91af;"&gt;CommandQueue&lt;/span&gt; commandQueue, &lt;span style="color:#2b91af;"&gt;Command&lt;/span&gt; nextCommand)&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Start to listen for connections from a client.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;Trace&lt;/span&gt;.WriteLine(&lt;span style="color:#a31515;"&gt;&amp;quot;Waiting for a connection...&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Accept the connection. &lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// BeginAcceptSocket() creates the accepted socket.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; listener.BeginAcceptTcpClient(&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; DoAcceptTcpClientCallback,&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;AcceptTcpClientParameters&lt;/span&gt;(commandQueue, nextCommand, listener));&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#008000;"&gt;// Process the client connection.&lt;/span&gt;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; DoAcceptTcpClientCallback(&lt;span style="color:#2b91af;"&gt;IAsyncResult&lt;/span&gt; ar)&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;AcceptTcpClientParameters&lt;/span&gt; parameters = ar.AsyncState &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; &lt;span style="color:#2b91af;"&gt;AcceptTcpClientParameters&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;(parameters == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:#2b91af;"&gt;TcpClient&lt;/span&gt; client = parameters.TcpListener.EndAcceptTcpClient(ar);&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; parameters.NextCommand.Process(parameters.CommandQueue, client);&lt;/pre&gt;
&lt;pre style="background:cornsilk;margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;I find this use of nested types to be more object-oriented (the needs of the DoAcceptTcpClientCallback are abstracted), more intention revealing, better implements Single Responsibility Principle (SRP), better separates concerns, more maintainable and more agile.&lt;/p&gt;
&lt;p&gt;Now, to be clear; this is forced set of circumstances.&amp;nbsp; You&amp;#39;re using a library that implements the APM (right?&amp;nbsp; You haven&amp;#39;t implemented APM yourself...).&amp;nbsp; But, that&amp;#39;s my point--nested types are almost essential in a given set of circumstances.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2008%2f07%2f15%2fnested-types.aspx"&gt;&lt;img border="0" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2008%2f07%2f15%2fnested-types.aspx" alt="kick it on DotNetKicks.com" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1640904" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Software+Development/default.aspx">Software Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/TCP/default.aspx">TCP</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Asynchronous+Programming+Model+_2800_APM_2900_/default.aspx">Asynchronous Programming Model (APM)</category></item><item><title>Upcoming C# 3 Guidance From Microsoft</title><link>http://msmvps.com/blogs/peterritchie/archive/2008/03/13/upcoming-c-3-guidance-from-microsoft.aspx</link><pubDate>Thu, 13 Mar 2008 15:46:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1542087</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1542087</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2008/03/13/upcoming-c-3-guidance-from-microsoft.aspx#comments</comments><description>&lt;p&gt;Mircea Trofin has some &lt;a class="" href="http://blogs.msdn.com/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx"&gt;design guidelines with regard to some C# 3 language additions&lt;/a&gt; (that I assume will make it into a&amp;nbsp;revised Framework Design Guidelines of some sort).&amp;nbsp; They more less agree with the &lt;a class="" href="http://www.code-magazine.com/Article.aspx?quickid=0801061"&gt;guidelines I published&lt;/a&gt; in Code Magazine a while ago.&amp;nbsp; There are some slight differences:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Consider &lt;/strong&gt;using extension methods in any of the following scenarios: to provide helper functionally relevant to every implementation of an interface&lt;/em&gt;... and,&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Do&lt;/strong&gt; define extension methods in the same namespace as the extended type, if the type is an interface, and if the extension methods are meant to be used in most or all cases.&lt;/em&gt;&amp;nbsp; This applies to framework designers that are publishing interfaces but also want to publish callable methods that apply to all implementation of those interfaces.&amp;nbsp; My article approaches the guidelines more from a non-framework designer.&amp;nbsp; I do agree that extension methods to extend interfaces is very useful and is probably one of the most adept use of extension methods.&amp;nbsp; Although, I think the wording of this guideline could use improvement.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Avoid&lt;/strong&gt; defining extension methods on System.Object, unless absolutely necessary&lt;/em&gt;.&amp;nbsp; Good advice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Do not&lt;/strong&gt; define extension methods pertaining to a feature in namespaces normally associated with other features.&amp;nbsp; Instead define them in the namespace associated with the feature they belong to, or a namespace of it.&lt;/em&gt;&amp;nbsp; This is really unclear (and seems to suggest contradicting the first guideline:&amp;nbsp;&lt;em&gt;Avoid frivolous use of the extension methods feature when defining methods on a new type.&amp;nbsp; Use the canonical, language-specific means for defining type members&lt;/em&gt;).&amp;nbsp; I&amp;#39;m assuming the jist of this is, as a framework designer, don&amp;#39;t arbitrarily put extension methods in the namespace of the type the method applies to, consider putting the extension method in a more applicable namespace, if possible.&amp;nbsp; For example, if you want to declare an extension method &amp;quot;Forward&amp;quot; for Telecom.INode implementations, putting the method in a &amp;quot;Routing&amp;quot; namespace&amp;nbsp;would be better than arbitrarily putting it in the &amp;quot;Telecom&amp;quot; namespace.&amp;nbsp; I&amp;#39;ve changed the Mircea&amp;#39;s guidance slightly to use a interface in the example--which I think makes it more clear.&lt;/p&gt;
&lt;p&gt;Mircea also includes &lt;em&gt;&lt;strong&gt;Consider&lt;/strong&gt; using extension methods in any of the following scenarios:... when object model considerations would dictate taking a dependency on some assuming but taking such a dependency would break dependency management rules&lt;/em&gt;.&amp;nbsp; This means, should you need to add a method to a class but adding that method would create cyclic dependency or would cause a lower level assembly/class to be dependant on a higher level class, break the method out into another assembly as an extension method.&amp;nbsp; Use this advice with caution; I would argue that if you think you need a method like this at all (even if implemented as an extension method), you likely have some design problems and should only be considered when revising a published framework, and not when creating a new framework.&lt;/p&gt;
&lt;p&gt;Another tidbit of guidance that came about after I wrote the article and Mircea doesn&amp;#39;t mention is that &lt;a class="" href="http://codebetter.com/blogs/gregyoung/archive/2007/12/05/a-use-for-extension-methods.aspx"&gt;extension methods can make writing fluent interfaces much cleaner&lt;/a&gt; by separating the state management concern of supporting a fluent interface&amp;nbsp;from the class that it applies to.&lt;/p&gt;
&lt;p&gt;Thoughts?&amp;nbsp; Any additional guidance you feel has been overlooked (with regard to extension methods and LINQ)?&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2008%2f03%2f13%2fupcoming-c-3-guidance-from-microsoft.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fmsmvps.com%2fblogs%2fpeterritchie%2farchive%2f2008%2f03%2f13%2fupcoming-c-3-guidance-from-microsoft.aspx" border="0" /&gt;&lt;/a&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1542087" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/DevCenterPost/default.aspx">DevCenterPost</category></item><item><title>CoDe Magazine Article.</title><link>http://msmvps.com/blogs/peterritchie/archive/2008/02/04/code-magazine-article.aspx</link><pubDate>Mon, 04 Feb 2008 18:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1495563</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1495563</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2008/02/04/code-magazine-article.aspx#comments</comments><description>&lt;p&gt;The January/February edition of &lt;a class="" href="http://www.code-magazine.com/Index.aspx"&gt;Code Magazine&lt;/a&gt; includes my article &amp;quot;&lt;a class="" href="http://www.code-magazine.com/Article.aspx?quickid=0801061"&gt;C# 3.0 Syntax Additions-Design Guidelines&lt;/a&gt;&amp;quot;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1495563" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category></item><item><title>Visual C# Developer Center Article</title><link>http://msmvps.com/blogs/peterritchie/archive/2008/01/03/visual-c-developer-center-article.aspx</link><pubDate>Thu, 03 Jan 2008 20:27:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1435703</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1435703</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2008/01/03/visual-c-developer-center-article.aspx#comments</comments><description>&lt;p&gt;My latest &lt;a class="" href="http://msdn2.microsoft.com/vcsharp"&gt;Visual C# Developer Center&lt;/a&gt; Article&amp;nbsp;Inferred&amp;nbsp;&lt;a class="" href="http://msdn2.microsoft.com/en-ca/vcsharp/bb978522.aspx"&gt;Typing with Factory Methods as Extension Methods&lt;/a&gt;&amp;nbsp;is now online.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1435703" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+Development/default.aspx">.NET Development</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category></item><item><title>New warning CS0809 in C# 3 (Visual Studio 2008)</title><link>http://msmvps.com/blogs/peterritchie/archive/2007/11/26/new-warning-cs0809-in-c-3-visual-studio-2008.aspx</link><pubDate>Mon, 26 Nov 2007 20:31:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1358620</guid><dc:creator>PeterRitchie</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/peterritchie/rsscomments.aspx?PostID=1358620</wfw:commentRss><comments>http://msmvps.com/blogs/peterritchie/archive/2007/11/26/new-warning-cs0809-in-c-3-visual-studio-2008.aspx#comments</comments><description>&lt;p&gt;There were several breaking changes (fixes) in C# 3 from C# 2.&amp;nbsp; One is the ability to attribute a member override with ObsoleteAttribute without also attributing it the virtual member in the base class.&lt;/p&gt;
&lt;p&gt;For example, the following will compile without error In C# 2 (Visual Studio 2005/.NET 2.0):&lt;/p&gt;
&lt;blockquote&gt;
&lt;div style="FONT-SIZE:10pt;BACKGROUND:white;COLOR:black;FONT-FAMILY:Courier New;"&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;using&lt;/span&gt; System;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;internal&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;BaseClass&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;virtual&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; Method()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;internal&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;DerivedClass&lt;/span&gt; : &lt;span style="COLOR:#2b91af;"&gt;BaseClass&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; [&lt;span style="COLOR:#2b91af;"&gt;Obsolete&lt;/span&gt;]&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;override&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; Method()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Progam&lt;/span&gt;&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;{&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;void&lt;/span&gt; Main()&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:#2b91af;"&gt;BaseClass&lt;/span&gt; baseClass = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;DerivedClass&lt;/span&gt;();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; baseClass.Method();&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="MARGIN:0px;"&gt;}&lt;/pre&gt;&lt;/div&gt;&lt;/blockquote&gt;
&lt;p&gt;This same code will generate a CS0809 warning with C# 3.&lt;/p&gt;
&lt;p&gt;This change was done because, as you can see in the example, if DerivedClass.Method is accessed via a BaseClass reference, the compiler can&amp;#39;t reliably warn you that you&amp;#39;re in fact calling an Obsolete method.&lt;/p&gt;
&lt;p&gt;In reality, even you you did call DerivedClass.Method() via a DerivedClass reference you still wouldn&amp;#39;t get a warning.&amp;nbsp; This may have something to do with a quirk in the way the compiler detects attributes with overrides and virtual methods; but I&amp;#39;m surmising.&lt;/p&gt;
&lt;p&gt;The fix, if you have access to the base class, is to attribute bot the base and the derived class member with ObsoleteAttribute.&amp;nbsp; If you don&amp;#39;t have access to the base class, you&amp;#39;ll have to live with or suppress the warning.&lt;br /&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1358620" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Design_2F00_Coding+Guidance/default.aspx">Design/Coding Guidance</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/Visual+Studio+2008/default.aspx">Visual Studio 2008</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0/default.aspx">C# 3.0</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://msmvps.com/blogs/peterritchie/archive/tags/C_2300_+3.0+Breaking+Changes/default.aspx">C# 3.0 Breaking Changes</category></item></channel></rss>