<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://srtsolutions.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>Effective C#</title><link>http://srtsolutions.com/blogs/effectivecsharp/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>error in Item 5, p. 37</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2007/07/25/error-in-item-5-p-37.aspx</link><pubDate>Wed, 25 Jul 2007 16:37:45 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:852</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=852</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2007/07/25/error-in-item-5-p-37.aspx#comments</comments><description>&lt;i&gt;Missing format string&lt;/i&gt;&lt;br /&gt;&lt;p&gt;On page 37, in item 5, the line of code that reads:&lt;/p&gt;&lt;pre&gt;    Console.WriteLine( string.Format( new CustomerFormatter(), &amp;quot;&amp;quot;, c1 );&lt;/pre&gt;&lt;p&gt;should read:&lt;/p&gt;&lt;pre&gt;    Console.WriteLine( string.Format( new CustomerFormatter(), &amp;quot;{0}&amp;quot;, c1 );&lt;/pre&gt;&lt;p /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=852" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+5/default.aspx">Item 5</category></item><item><title>P 19, (item 3)</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/07/16/p-19-item-3.aspx</link><pubDate>Sun, 16 Jul 2006 20:47:03 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:851</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=851</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/07/16/p-19-item-3.aspx#comments</comments><description>&lt;i&gt;missing char&lt;/i&gt;&lt;br /&gt;&lt;p&gt;The code at the bottom of p. 19 reads:&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;//Version two&lt;p /&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;try &lt;br /&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&amp;nbsp;&amp;nbsp; MyType t1;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;t = (MyType)o;&lt;p /&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;p&gt;It should be:&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;p /&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;try &lt;br /&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;{&lt;br /&gt;&lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&amp;nbsp;&amp;nbsp; MyType t1;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/font&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;t1 = (MyType)o;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;font face="Arial" size="2"&gt;&lt;span style="FONT-SIZE:10pt;FONT-FAMILY:Arial;"&gt;&lt;/span&gt;&lt;/font&gt;&lt;/p&gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=851" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+3/default.aspx">Item 3</category></item><item><title>p. 122 (Item 19)</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/07/07/p-122-item-19.aspx</link><pubDate>Fri, 07 Jul 2006 23:21:44 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:850</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=850</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/07/07/p-122-item-19.aspx#comments</comments><description>&lt;i&gt;Wrong word in 3rd paragraph&lt;/i&gt;&lt;br /&gt;&lt;p&gt;The second&amp;nbsp;sentence in the third paragraph reads: &amp;nbsp;&amp;nbsp; &amp;quot;It [IListSource] also has a containsListCollection property so that&amp;nbsp; users can modify the overall structure of the collection.&amp;quot;&lt;/p&gt;&lt;p&gt;It should read:&amp;nbsp; &amp;quot;It [IListSource] also has a containtsListCollection property so that users can &lt;strong&gt;navigate&lt;/strong&gt; the overall structure of the collection.&amp;quot;&lt;/p&gt;&lt;p&gt;(Bold indicates the change, not emphasis).&amp;nbsp; &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=850" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+19/default.aspx">Item 19</category></item><item><title>Poor word choice in Item 3</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/01/09/poor-word-choice-in-item-3.aspx</link><pubDate>Mon, 09 Jan 2006 17:58:39 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:849</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=849</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2006/01/09/poor-word-choice-in-item-3.aspx#comments</comments><description>&lt;i&gt;You could easily mis-interpret what I said about the as and is operators&lt;/i&gt;&lt;br /&gt;&lt;p&gt;At the bottom of page 18, in Item 3, I wrote this sentence:&lt;/p&gt;&lt;p&gt;&lt;em&gt;&amp;quot;If a particular object is not the requested type or is derived from the requested type, they fail.&amp;quot;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;A better choice would have been:&lt;/p&gt;&lt;font size="2"&gt;&lt;p&gt;&lt;em&gt;&amp;quot;If a particular object is not the requested type, nor a type derived from the requested type, they fail.&amp;quot;&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=849" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+3/default.aspx">Item 3</category></item><item><title>Errata: Item 10</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/11/15/errata-item-10.aspx</link><pubDate>Tue, 15 Nov 2005 08:54:48 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:848</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=848</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/11/15/errata-item-10.aspx#comments</comments><description>&lt;i&gt;p. 63.&lt;/i&gt;&lt;br /&gt;&lt;p&gt;Item 10 incorrectly implies that System.ValueType contains a static operator ==.&lt;/p&gt;&lt;p&gt;It doesn&amp;#39;t.&amp;nbsp; &lt;/p&gt;&lt;p&gt;However, many developers do create what seems like a simple solution:&lt;/p&gt;&lt;p&gt;struct MyType&lt;br /&gt;{&lt;br /&gt;&amp;nbsp; // data members elided.&lt;br /&gt;&amp;nbsp; static bool operator == ( MyType l, MyType r )&lt;br /&gt;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return l.Equals ( r );&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&amp;nbsp; // Note no override of Equals.&amp;nbsp;&amp;nbsp;&lt;br /&gt;}&lt;/p&gt;&lt;p&gt;That will cause the behavior I mentioned in the item. The reason is that ValueType.Equals() does use reflection to find the values of each field in the objects being compared.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=848" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+10/default.aspx">Item 10</category></item><item><title>Clarification:  Item 22</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/08/29/clarification-item-22.aspx</link><pubDate>Mon, 29 Aug 2005 18:22:00 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:847</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=847</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/08/29/clarification-item-22.aspx#comments</comments><description>&lt;p&gt;Elided code was not clearly marked&lt;br /&gt;Both listener classes on p. 134 should include a private declaration of the Logger Singleton class: &lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static Logger logger; &lt;/p&gt;
&lt;p&gt;&lt;br /&gt;This declaration was removed from the code listing, but not discussed in the text. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=847" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+22/default.aspx">Item 22</category></item><item><title>Errata: p. 24</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/08/16/errata-p-24.aspx</link><pubDate>Tue, 16 Aug 2005 06:52:26 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:846</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=846</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/08/16/errata-p-24.aspx#comments</comments><description>&lt;i&gt;2nd paragraph&lt;/i&gt;&lt;br /&gt;The sentence &amp;quot;The &lt;font face="courier new,courier,monospace"&gt;as&lt;/font&gt; operator returns true ...&amp;quot; Should read &amp;quot;The &lt;em&gt;is&lt;/em&gt; operator returns true ...&amp;quot;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=846" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+3/default.aspx">Item 3</category></item><item><title>Errata: p24</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/07/14/errata-p24.aspx</link><pubDate>Thu, 14 Jul 2005 23:59:56 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:845</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=845</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/07/14/errata-p24.aspx#comments</comments><description>&lt;i&gt;missing words&lt;/i&gt;&lt;br /&gt;&lt;p&gt;The sentence that says, &amp;quot;If you made a create a Newtype&amp;quot; should be &amp;quot;If you made a new class derived from Newtype&amp;quot;&lt;/p&gt;&lt;p /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=845" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+3/default.aspx">Item 3</category></item><item><title>Errata:  Missing words on p. 144</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/17/errata-missing-words-on-p-144.aspx</link><pubDate>Fri, 17 Jun 2005 19:49:56 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:844</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=844</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/17/errata-missing-words-on-p-144.aspx#comments</comments><description>&lt;i&gt;There really was a full sentence there&lt;/i&gt;&lt;br /&gt;&lt;p&gt;p. 144, Item 24, contains the following sentence:&amp;nbsp; &amp;quot;&lt;font size="2"&gt;The DefaultSort attribute e, the Name property.&amp;quot;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font size="2"&gt;What should be there is this:&lt;/font&gt;&lt;/p&gt;&lt;font size="2"&gt;&lt;font size="2"&gt;&lt;p&gt;&amp;quot;The DefaultSort attribute defines the default sorting property for the Customer class&lt;/p&gt;&lt;/font&gt;&lt;font face="Courier New" size="2"&gt;&amp;mdash;&lt;/font&gt;&lt;font size="2"&gt;in this case, the Name property.&amp;quot;&lt;/font&gt;&lt;/font&gt; &lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=844" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+24/default.aspx">Item 24</category></item><item><title>Exceptional conditions about exceptions</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/08/exceptional-conditions-about-exceptions.aspx</link><pubDate>Thu, 09 Jun 2005 00:11:29 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:843</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=843</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/08/exceptional-conditions-about-exceptions.aspx#comments</comments><description>&lt;i&gt;A number of subtle points about exception processing.&lt;/i&gt;&lt;br /&gt;&lt;p&gt;This is one of those lengthy discussions that get filed under &amp;ldquo;There are always exceptions&amp;rdquo;. And, it happens to be related to the guidance I wrote on exceptions in Effective C#.&lt;/p&gt;&lt;p&gt;First, the simple question:&lt;/p&gt;&lt;p&gt;&amp;ldquo;Recently, I and fellow developers have a very heated and passionate debate on whether or not it is appropriate to derive one&amp;#39;s application-specific exception from System.ApplicationException or System.Exception. (I was the lone voice, which now advocates the latter despite my past recommendation).&lt;br /&gt;So far Microsoft and all its documentation recommend what you stated in the book and I have been following this recommendation. But of late, particularly in Whidbey Beta 1, the recommendation has changed. Even FxCop 1.312 for Whidbey has changed.&lt;br /&gt;It now recommends the application-specific exception *should* derive from System.Exception instead.&lt;br /&gt;I was initially furious with FxCop but after doing research, particularly SLAR (.Net Framework Standard Library Annotated Reference) and this URL go further to suggest the BCL team has admission of mistake: &lt;span class="Hyperlink"&gt;http://blogs.msdn.com/brada/archive/2004/03/25/96&lt;/span&gt;&lt;span class="Hyperlink"&gt;2&lt;/span&gt;&lt;span class="Hyperlink"&gt;51.aspx&lt;/span&gt;&amp;rdquo;&lt;/p&gt;&lt;p&gt;Well, yeah, we all goofed.  It turns out that creating an application specific base class for exceptions doesn&amp;rsquo;t buy anything.  In fact, it only makes writing good catch clauses harder.  As I pointed out in Item 44, the main reason to create new exception clauses is to facilitate catching different errors and responding to them with different actions. Knowing that an exception was generated in application code vs. library code doesn&amp;rsquo;t really play into that decision. In fact, all it does is introduce an extra level of complexity in the class hierarchy.  The world is a simpler place without using ApplicationException.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;And now, the subtle correct behavior in Item 44:&lt;/p&gt;&lt;p&gt;&amp;ldquo;Also because Exception is derived from ISerializable, I don&amp;#39;t seem to recall seeing the mentioning of ISerializable.GetObjectData(), which is mentioned in Item 25).&amp;rdquo;&lt;/p&gt;&lt;p&gt;Correct, I did not add a GetObjectData() method in any of the examples in Item 44. The reason is simple: None of these classes add any data fields not already found in the base class, System.Exception. For that reason the correct implementation of any derived GetObjectData would do nothing except call the base class, providing no extra functionality. I should have explained my reason for not including it, but the samples are correct without it.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;And finally, the tough one:&lt;/p&gt;&lt;p&gt;&amp;ldquo;In relation to the use of Inner Exception, I have two minds about it. One is if you provide a form of abstraction where the client of your class/assembly needs not be aware of the implementation details. If the class designer wisely implements an Application-specific exception in the public interface (which exceptions are part of it) to support exception translation.&lt;/p&gt;&lt;p&gt;If the class designer unwittingly uses inner exception to embed the exception thrown by the implementation assembly, then this forces the client also to reference the implementation assembly in order to deserialize the application-specific exception. This to me is a break in abstraction. The problem is particularly acute in cross app domain calls, such as remoting. For instance class that support remoting service from a Data Access Layer. The client should not need to include say SqlClient in order to deserialize an exception thrown from the DAL.&lt;/p&gt;&lt;p&gt;The other area where the embedded inner exception can hurt is in those  assembly that are loaded dynamically via Assembly.Load() using configuration details, generally in their own app domain. When the exception is deserialized it would also need to assembly supporting the inner exception to be available on the receiving side. Failure to have them can result in a deserialization exception.&lt;/p&gt;&lt;p&gt;In this usage, I tend to recommend to my fellow developers to avoid embedding exception. But rather constructed an exception message that include enough details of the implementation detail for technical staff to perform diagnostic.&amp;rdquo;&lt;/p&gt;&lt;p&gt;This is the difficult question, because it touches on many edge cases.  First, let&amp;rsquo;s cover the normal case: You should fill in the InnerException property, because it&amp;rsquo;s how you preserve as much information as possible about the original error. Failure to do so means that the technical staff loses that information.&lt;/p&gt;&lt;p&gt;Now let&amp;rsquo;s look at the two cases my reader mentioned. First, let&amp;rsquo;s cover remoting.  Ideally, you&amp;rsquo;d like to preserve the InnerException property. But, it&amp;rsquo;s just not safe. As the reader points out, if the implementation of the runtime class used in the InnerException isn&amp;rsquo;t available on the client, the client gets a SerializationException. That effectively loses all information in your original exception, so it doesn&amp;rsquo;t help anyone. &lt;/p&gt;&lt;p&gt;You might be tempted to look at the runtime type of the exception and include it as the InnerException property if it is delivered with the framework, and therefore available on the client machine.  That&amp;rsquo;s a mistake, because you would need to walk all the InnerException property of each inner exception to ensure that you never find a type that might not be delivered to the client. &lt;/p&gt;&lt;p&gt;The Assembly.Load() gives similar results but for different reasons. Once again, you don&amp;rsquo;t know what domain into which you code will be loaded.  If an exception type (or any other type, for that matter), gets passed across the domain boundary, your client process must catch serialization exceptions.&lt;/p&gt;&lt;p&gt;The root cause in both cases is that an object is being passed across process boundaries. As an aside, you can create the same problems by returning a derived class where a base class was specified.  If the derived class implementation is not available to the client process, it cannot be serialized, and the client must catch serialization exceptions.&lt;/p&gt;&lt;p&gt;So, what should you do?  Well, this is one of the reasons I prefer an SOA model, or web services implementation, to communicate between processes. The Xml Serializer is more resilient in these kinds of situations. In fact, you can&amp;rsquo;t really throw an exception from a web service to the client application. Instead, you return an error document. &lt;/p&gt;&lt;p&gt;If you have chosen remoting and you&amp;rsquo;re planning to stick with it, you just have to remember that the app domain boundary is always a special case, and all the concrete types that are passed through that boundary must be available on both sides of the boundary. As the reader mentions, you need to use some other technique to preserve exception information.  My own preference would be to log all information about the exception on the server, using something like the Exception Processing block in the Enterprise Library. After that&amp;rsquo;s done, you can create a new exception that references the logged information and sends that to the client for client side processing and reporting.&lt;/p&gt;&lt;p&gt;Inter-process (and app domain) boundaries are edge cases, and you need to take special care with information that crosses those boundaries, including exceptions.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=843" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+44/default.aspx">Item 44</category></item><item><title>.NET Framework changes affecting Items 9, 10</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/08/net-framework-changes-affecting-items-9-10.aspx</link><pubDate>Wed, 08 Jun 2005 15:53:03 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:842</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=842</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/06/08/net-framework-changes-affecting-items-9-10.aspx#comments</comments><description>&lt;i&gt;The advice is still proper, but the justification is somewhat different.&lt;/i&gt;&lt;br /&gt;&lt;p&gt;The 2.0 version of the .NET framework has changed the way they implement ValueType.Equals() and ValueType.GetHashCode(). This affects some of the justification for my advice in items 9 and 10.  &lt;/p&gt;&lt;p&gt;I explained in Item 9 that these methods use Reflection to determine if the values stored are equal. Further, that as a performance improvement, only the first field in the value type was compared, instead of each field. A similar algorithm was used in ValueType.GetHashCode(): This method returned the hash code of the first field in the value type.&lt;/p&gt;&lt;p&gt;This behavior changes in 2.0.  Beta 1 and Beta 2 now use all the fields in a value type to determine equality, and to calculate the hash code. &lt;/p&gt;&lt;p&gt;These changes do not fundamentally affect the advice I set forth in Items 9 and 10.  (In fact, if you are already following my advice, the changes to the implementation of these methods will be transparent to you.) You should still override both methods, Equals and GetHashCode) for ValueTypes. While the implementations in the 2.0 framework are more correct than their predecessors, they will have a negative impact on performance because of their use of reflection. Furthermore, by creating your own implementation, you shield yourself against this type of version-to-version implementation changes.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=842" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+9/default.aspx">Item 9</category><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+10/default.aspx">Item 10</category></item><item><title>Question on Array Recommendations</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/02/28/question-on-array-recommendations.aspx</link><pubDate>Mon, 28 Feb 2005 16:29:16 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:841</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=841</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/02/28/question-on-array-recommendations.aspx#comments</comments><description>&lt;i&gt;They are slightly different than those from the P &amp;amp; P Guide.&lt;/i&gt;&lt;br /&gt;&lt;h1&gt;Question on Array Recommendations.&lt;/h1&gt;&lt;p&gt;I finished your book a few days ago. It was a fun read, and I think you covered a lot of good areas for code improvement. I found one of your recommendations that contradicts with something I found in the Patterns and Practices Performance and Scalability book from Microsoft dealing with Multidimensional Arrays vs Jagged Arrays. You seem to be in favor of the Multidimensional Arrays over Jagged (Item 40, page 231-232). Here&amp;#39;s what the P&amp;amp;P book has to say on that:&lt;/p&gt;&lt;p&gt;Chapter 5, page 241-242:&lt;/p&gt;&lt;p&gt;&amp;quot;Use Jagged Arrays Instead of Multidimensional Arrays&lt;/p&gt;&lt;p&gt;A jagged array is a single dimensional array of arrays. The elements of a jagged array can be of different dimensions and sizes. Use jagged arrays instead of multidimensional arrays to benefit from MSIL performance optimizations. MSIL has specific instructions that target single dimensional zero-based arrays (SZArrays) and access to this type of array is optimized. In contrast, multidimensional arrays are accessed using the same generic code for all types, which results in boxing and unboxing for arrays of primitive types.&amp;quot;&lt;/p&gt;&lt;p&gt;They then get into some MSIL code comparing the two.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;h1&gt;My Response:&lt;/h1&gt;&lt;p&gt;This is one of those low-level performance issues where the performance metrics depend on the particular program.  I&amp;#39;ll get to the performance characteristics in a moment.&lt;/p&gt;&lt;p&gt;My overriding reason for recommending multi-dimensional arrays stems from ease of use, and maintenance.  A multi-dimensional array is a single structure. Simulating multiple dimensions using jagged arrays is more complex: You create one array per row, plus the outer array. Quite simply, it&amp;#39;s easier to get wrong, resulting in null reference exceptions.&lt;/p&gt;&lt;p&gt;This added complexity manifests itself in many ways. First, you write more initialization code (shown on p. 230-231 of Effective C#). Iterating all the members of a jagged array is more complex as well. A single for or foreach loop gets replaced with nested loops. I discuss this on p. 232-233. &lt;/p&gt;&lt;p&gt;While this may be simple code when you intend to model a multi-dimensional array using jagged arrays, there is no guarantee that all rows have the same number of elements. This also complicated column-wise traversals: You should check that each row has enough elements before simply assuming it works.  If you want to support a single enumerator for a jagged array, you must write your own. It&amp;#39;s already available in a multi-dimensional array.&lt;/p&gt;&lt;p&gt;These differences make me lean toward simplicity rather than speed. Quite frankly, a little slower but more maintainable code will scale better than overly optimized but harder to maintain code. That means I prefer the multi-dimensional array.&lt;/p&gt;&lt;p&gt;Finally, I&amp;#39;ll address the performance issues.  It depends on what you measure, and where your programs bottlenecks are:&lt;/p&gt;&lt;p&gt;A multi-dimensional array is one allocation; a jagged array causes N+1 allocations, where N is the number of rows. That has some cost. &lt;/p&gt;&lt;p&gt;Row-wise traversals will be faster for jagged arrays, as pointed out in the P&amp;amp;P guide. &lt;/p&gt;&lt;p&gt;Column-wise traversals will be faster for multidimensional arrays, as I point out in p. 231. &lt;/p&gt;&lt;p&gt;In all three cases, the differences will be small. You will only see the difference for an operation that is repeated very often. Before you make this kind of a change, you should profile code and determine which version is fastest. And, you should know that the speed difference is significant enough to justify the change.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=841" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+40/default.aspx">Item 40</category></item><item><title>Questions and answers about events and threads</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/02/14/questions-and-answers-about-events-and-threads.aspx</link><pubDate>Mon, 14 Feb 2005 08:22:16 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:840</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=840</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/02/14/questions-and-answers-about-events-and-threads.aspx#comments</comments><description>&lt;i&gt;This pertains to Item 22, and Item 45.&lt;/i&gt;&lt;br /&gt;&lt;h1&gt;Question 1:&lt;/h1&gt;&lt;p class="NormalWeb"&gt;&lt;span style="FONT-FAMILY:Arial;"&gt;Can you further explain the idiom you recommend on top of page 133 &lt;/span&gt;&lt;span style="FONT-FAMILY:Arial;"&gt;(see below) &lt;/span&gt;&lt;span style="FONT-FAMILY:Arial;"&gt;to raise an event. Specifically, how does making a copy of the reference provide protection?&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;// add a message, and log it.&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;public void AddMsg ( int priority, string msg )&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;{&lt;/span&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;&amp;nbsp; // This idiom discussed below.&lt;/span&gt;&lt;span style="COLOR:#000000;FONT-FAMILY:LucidaTypewriter;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&amp;nbsp; AddMessageEventHandler l = Log;&lt;/span&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&amp;nbsp; if ( l != null )&lt;/span&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; l ( null, new LoggerEventArgs( priority, msg ) );&lt;/span&gt;&lt;br /&gt;&lt;span style="COLOR:#231f20;FONT-FAMILY:LucidaTypewriter;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;&lt;p class="NormalWeb"&gt;&lt;span style="FONT-FAMILY:Arial;"&gt;In my mind a &amp;quot;copy of a reference&amp;quot; is, well, just a copy-of-a-reference, which would not prevent the referenced object from being changed elsewhere. I would agree that a copy of the underlying _object_ would provide protection, but that doesn&amp;#39;t seem to be what&amp;#39;s going on here.&lt;/span&gt;&lt;/p&gt;&lt;h1&gt;Answer 1:&lt;/h1&gt;&lt;p&gt;This idiom does work because of the behavior of the Add and Remove accessors for an event. If another thread calls Remove(), that does not modify the invocation list you&amp;rsquo;ve copied to the local variable &amp;lsquo;l&amp;rsquo;. Rather, it creates a new invocation list with no targets. Your invocation list is still valid. You are not making a deep copy of the invocation list, but any other thread the modifies your invocation list does. &lt;/p&gt;&lt;h1&gt;Question 2:&lt;/h1&gt;&lt;p class="NormalWeb"&gt;&lt;span style="FONT-FAMILY:Arial;"&gt;Also while on this topic, do you recommend protecting the actual event call with a Try/Catch as a way to protect against exception-throwing event handlers (that others might write, of course)? Not sure that there would be anything to do in the Catch, maybe just Catch {}. Interested to know what you think.&lt;/span&gt;&lt;/p&gt;&lt;h1&gt;Answer 2:&lt;/h1&gt;&lt;p&gt;It varies. I believe that event handlers should never throw exceptions. (See Item 45, p. 270). However, I don&amp;rsquo;t believe that you can always count on others to follow that rule. If you are creating libraries that will be used by a large audience, you should be very defensive and wrap event handler invocations with try / catch. When you are creating closed systems, and you can ensure that none of the event handlers could possibly throw exceptions, I find that the simpler syntax easier to read and maintain.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=840" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+22/default.aspx">Item 22</category><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+45/default.aspx">Item 45</category></item><item><title>P. 111, Item 17</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/01/21/p-111-item-17.aspx</link><pubDate>Fri, 21 Jan 2005 02:09:33 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:839</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=839</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/01/21/p-111-item-17.aspx#comments</comments><description>&lt;i&gt;Implement the Standard Dispose Idiom&lt;/i&gt;&lt;br /&gt;&lt;p&gt;At the bottom of the page, the line:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;GC.SuppressFinalization( true );&lt;/font&gt;&lt;/p&gt;&lt;p&gt;should be:&lt;/p&gt;&lt;p&gt;&lt;font face="courier new,courier,monospace"&gt;GC.SuppressFinalize( this );&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Found by Barrie Green.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=839" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+17/default.aspx">Item 17</category></item><item><title>Question on Item 4</title><link>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/01/11/question-on-item-4.aspx</link><pubDate>Tue, 11 Jan 2005 20:56:33 GMT</pubDate><guid isPermaLink="false">727bb5a1-3d8b-4cbc-a411-ac1a71136f7d:836</guid><dc:creator>wwagner</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://srtsolutions.com/blogs/effectivecsharp/rsscomments.aspx?PostID=836</wfw:commentRss><comments>http://srtsolutions.com/blogs/effectivecsharp/archive/2005/01/11/question-on-item-4.aspx#comments</comments><description>&lt;i&gt;MSDN uses a different idiom to support multiple conditions on an attribute.  I think it has a number of shortcomings.&lt;/i&gt;&lt;br /&gt;&lt;h1&gt;Question: Marc Jennings writes:&lt;/h1&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;In the section on Conditionals you say that in order to create a method that will fire if more than one condition is true (logical AND), you need to use&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;#if (VAR1 &amp;amp;&amp;amp; VAR2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#define BOTH&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#endif&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;However, it is possible to chain the conditionals together (according to MSDN, anyway&amp;hellip;)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&amp;lt;QUOTE from=&amp;rdquo;MSDN&amp;rdquo;&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="HTMLPreformatted"&gt;&lt;span&gt;[Conditional(&amp;quot;A&amp;quot;)] public static void IfAandB( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; AandBPrivate( ); &lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;[Conditional(&amp;quot;B&amp;quot;)] static void AandBPrivate( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; /* Code to execute when both A and B are defined... */&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="NormalWeb"&gt;&lt;span&gt;Call &lt;/span&gt;&lt;span class="HTMLCode" style="font-family:Courier New;"&gt;IfAandB&lt;/span&gt;&lt;span&gt;; if both &lt;/span&gt;&lt;span class="HTMLCode" style="font-family:Courier New;"&gt;A &lt;/span&gt;&lt;span&gt;and &lt;/span&gt;&lt;span class="HTMLCode" style="font-family:Courier New;"&gt;B &lt;/span&gt;&lt;span&gt;are defined, &lt;/span&gt;&lt;span class="HTMLCode" style="font-family:Courier New;"&gt;AandBPrivate &lt;/span&gt;&lt;span&gt;will execute.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;&amp;lt;/QUOTE&amp;gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Arial;"&gt;Is there any reason to use your method above the MS one?&amp;nbsp; &lt;/span&gt;&lt;/p&gt;&lt;h1&gt;&lt;span&gt;Answer:&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;&lt;span&gt;I chose using the #if logic over chaining conditionals because it produces code that is much easier to maintain.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;Using the idiom I preferred, the MSDN sample would look like this:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;#if (&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;A&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;B&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#define BOTH&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;[Conditional(&amp;quot;&lt;/span&gt;&lt;span&gt;BOTH&lt;/span&gt;&lt;span&gt;&amp;quot;)] static void AandBPrivate( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; /* Code to execute when both A and B are defined... */&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;&lt;br /&gt;I look at the top of the file to find any defined environment variables. And, the single environment variable used to control the compilation of a function is found on the method in question. The sample from MSDN can be perverted in a couple ways. First, I can easily circumvent the first check:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;/* No conditional attribute */ &lt;/span&gt;&lt;span&gt;static void BPrivate( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;AandBPrivate( );&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;The code inside AandBPrivate() can be accessed when only B is defined. That certainly looks like it was not intended.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;The MSDN idiom does not scale well either.  Putting the Boolean logic in the conditional, I can easily create more complicated expressions:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;#if (&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;A&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;B &amp;amp;&amp;amp; C &amp;amp;&amp;amp; D&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;)&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;br /&gt;#define ALL&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#endif&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;To do the same thing following the MSDN idiom requires this:&lt;/span&gt;&lt;/p&gt;&lt;p class="HTMLPreformatted"&gt;&lt;span&gt;[Conditional(&amp;quot;A&amp;quot;)] public static void IfAandB( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; AandBPrivate( ); &lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;[Conditional(&amp;quot;B&amp;quot;)] static void AandBPrivate( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;AandBAndCPrivate( );&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;[Conditional(&amp;quot;C&lt;/span&gt;&lt;span&gt;&amp;quot;)] static void AandB&lt;/span&gt;&lt;span&gt;andC&lt;/span&gt;&lt;span&gt;Private( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;AandBAndCandDPrivate( );&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;[Conditional(&amp;quot;D&lt;/span&gt;&lt;span&gt;&amp;quot;)] static void AandB&lt;/span&gt;&lt;span&gt;andCandD&lt;/span&gt;&lt;span&gt;Private( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;AandBAndCandDPrivate( );&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;It gets maddening fairly quickly.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span&gt;Finally, putting the conditionals at the top of the file means I can add methods that are dependent on the absence of an environment variable, which is not supported by the conditional attribute:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Courier New;"&gt;#if (&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt; ! D &lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;)&lt;/span&gt;&lt;span style="font-family:Courier New;"&gt;&lt;br /&gt;#define NotD&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Courier New;"&gt;#endif&lt;/span&gt;&lt;/p&gt;&lt;p class="HTMLPreformatted"&gt;&lt;span&gt;[Conditional(&amp;quot;NotD&lt;/span&gt;&lt;span&gt;&amp;quot;)] static void &lt;/span&gt;&lt;span&gt;NotD&lt;/span&gt;&lt;span&gt;Private( ) &lt;/span&gt;&lt;br /&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&lt;br /&gt;  /* contents elided. */&lt;/span&gt;&lt;br /&gt;&lt;span&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://srtsolutions.com/aggbug.aspx?PostID=836" width="1" height="1"&gt;</description><category domain="http://srtsolutions.com/blogs/effectivecsharp/archive/tags/Item+4/default.aspx">Item 4</category></item></channel></rss>