<?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>Jon Skeet: Coding Blog : Books</title><link>http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx</link><description>Tags: Books</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Where do you benefit from dynamic typing?</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/11/17/where-do-you-benefit-from-dynamic-typing.aspx</link><pubDate>Tue, 17 Nov 2009 07:31:48 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1740168</guid><dc:creator>skeet</dc:creator><slash:comments>52</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1740168</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1740168</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/11/17/where-do-you-benefit-from-dynamic-typing.aspx#comments</comments><description>&lt;p&gt;Disclaimer: I don&amp;#39;t want this to become a flame war in the comments. I&amp;#39;m coming from a position of ignorance, and well aware of it. While I&amp;#39;d like this post to provoke &lt;em&gt;thought&lt;/em&gt;, it&amp;#39;s not meant to be provocative in the common use of the term.&lt;/p&gt;  &lt;p&gt;Chapter 14 of C# in Depth is about dynamic typing in C#. A couple of reviewers have justifiably said that I&amp;#39;m fairly keen on the mantra of &amp;quot;don&amp;#39;t use dynamic typing unless you need it&amp;quot; – and that possibly I&amp;#39;m doing dynamic typing a disservice by not pointing out more of its positive aspects. I completely agree, and I&amp;#39;d love to be more positive – but the problem is that I&amp;#39;m not (yet) convinced about why dynamic typing is something I &lt;em&gt;would&lt;/em&gt; want to embrace.&lt;/p&gt;  &lt;p&gt;Now I want to start off by making something clear: this is meant to be about dynamic typing. Often advocates for dynamically typed languages will mention:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Read-eval-print_loop"&gt;REPL&lt;/a&gt; (read-eval-print-loop) abilities which allow for a very fast feedback loop while experimenting&lt;/li&gt;    &lt;li&gt;Terseness – the lack of type names everywhere makes code shorter&lt;/li&gt;    &lt;li&gt;Code evaluated at execution time (so config files can be scripts etc)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I don&amp;#39;t count any of these as benefits of dynamic typing per se. They&amp;#39;re benefits which often come alongside dynamic typing, but they&amp;#39;re not dependent on dynamic typing. The terseness argument is the one most closely tied to their dynamic nature, but various languages with powerful type inference show that being statically typed doesn&amp;#39;t mean having to specify type names everywhere. (C#&amp;#39;s &lt;em&gt;var&lt;/em&gt; keyword is a very restricted form of type inference, compared with – say – that of F#.)&lt;/p&gt;  &lt;p&gt;What I&amp;#39;m talking about is binding being performed at execution time and &lt;em&gt;only&lt;/em&gt; at execution time. That allows for:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Duck typing&lt;/li&gt;    &lt;li&gt;Dynamic reaction to previously undeclared messages&lt;/li&gt;    &lt;li&gt;Other parts of dynamic typing I&amp;#39;m unaware of (how could there not be any?)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;What I&amp;#39;m interested in is how often these are used within &lt;em&gt;real world&lt;/em&gt; (rather than demonstration) code. It may well be that I&amp;#39;m suffering from &lt;a href="http://c2.com/cgi/wiki?BlubParadox"&gt;Blub&amp;#39;s paradox&lt;/a&gt; – that I can&amp;#39;t see the valid uses of these features simply because I haven&amp;#39;t used them enough. Just to be clear, I&amp;#39;m not saying that I &lt;em&gt;never&lt;/em&gt; encounter problems where I would welcome dynamic typing – but I don&amp;#39;t run into them every day, whereas I get help from the compiler every day.&lt;/p&gt;  &lt;p&gt;Just as an indicator of how set in my statically typed ways I am, at the recent Stack Overflow DevDays event in London, Michael Sparks went through &lt;a href="http://norvig.com/spell-correct.html"&gt;Peter Norvig&amp;#39;s spelling corrector&lt;/a&gt;. It&amp;#39;s a neat piece of code (and yes, I&amp;#39;ll finish that port some time) but I kept finding it hard to understand simply because the types weren&amp;#39;t spelled out. Terseness can certainly be beneficial, but in this case I would personally have found it simpler if the variable and method types had been explicitly declared.&lt;/p&gt;  &lt;p&gt;So, for the dynamic typing fans (and I&amp;#39;m sure several readers will come into that category):&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;How often do you take advantage of dynamic typing in a way that really wouldn&amp;#39;t be feasible (or would be very clunky) in a statically typed language?&lt;/li&gt;    &lt;li&gt;Is it usually the same single problem which crops up regularly, or do you find a wide variety of problems benefit from dynamic typing?&lt;/li&gt;    &lt;li&gt;When you declare a variable (or first assign a value to a variable, if your language doesn&amp;#39;t use explicit declarations) how often do you really either not know its type or want to use some aspect of it which wouldn&amp;#39;t typically have been available in a statically typed environment?&lt;/li&gt;    &lt;li&gt;What balance do you find in your use of duck typing (the same method/member/message has already been declared on multiple types, but there&amp;#39;s no common type or interface) vs truly dynamic reaction based on introspection of the message within code (e.g. building a query based on the name of the method, such as FindBooksByAuthor(&amp;quot;Josh Bloch&amp;quot;))?&lt;/li&gt;    &lt;li&gt;What aspects of dynamic typing do I appear to be completely unaware of?&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Hopefully someone will be able to turn the light bulb on for me, so I can be more genuinely enthusiastic about dynamic typing, and perhaps even diversify from my comfort zone of C#…&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1740168" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/General/default.aspx">General</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Contract classes and nested types within interfaces</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/10/31/contract-classes-and-nested-types-within-interfaces.aspx</link><pubDate>Sat, 31 Oct 2009 22:04:54 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1736652</guid><dc:creator>skeet</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1736652</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1736652</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/10/31/contract-classes-and-nested-types-within-interfaces.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve just been going through some feedback for the draft copy of the second edition of C# in Depth. In the contracts section, I have an example like this:&lt;/p&gt;  &lt;div class="code"&gt;[ContractClass(&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(ICaseConverterContracts))]     &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; ICaseConverter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text);     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;[ContractClassFor(&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(ICaseConverter))]     &lt;br /&gt;&lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; ICaseConverterContracts : ICaseConverter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; ICaseConverter.Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Contract.Requires(text != &lt;span class="Keyword"&gt;null&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Contract.Ensures(Contract.Result&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;() != &lt;span class="Keyword"&gt;null&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;default&lt;/span&gt;(&lt;span class="ReferenceType"&gt;string&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt; ICaseConverterContracts() {}     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; InvariantUpperCaseFormatter : ICaseConverter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;string&lt;/span&gt; Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text)&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt; text.ToUpperInvariant();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;The point is to demonstrate how contracts can be specified for interfaces, and then applied automatically to implementations. In this case, &lt;code&gt;ICaseConverter&lt;/code&gt; is the interface, &lt;code&gt;ICaseConverterContracts&lt;/code&gt; is the &lt;i&gt;contract class&lt;/i&gt; which specifies the contract for the interface, and &lt;code&gt;InvariantUpperCaseFormatter&lt;/code&gt; is the real implementation. The binary rewriter effectively copies the contract into each implementation, so you don&amp;#39;t need to duplicate the contract in the source code.&lt;/p&gt;  &lt;p&gt;The reader feedback asked where the contract class code should live - should it go in the same file as the interface itself, or in a separate file as normal? Now normally, I&amp;#39;m firmly of the &amp;quot;one top-level type per file&amp;quot; persuasion, but in this case I think it makes sense to keep the contract class with the interface. It has no meaning without reference to the interface, after all - it&amp;#39;s not a real implementation to be used in the normal way. It&amp;#39;s essentially metadata. This does, however, leave me feeling a little bit dirty. What I&amp;#39;d &lt;em&gt;really&lt;/em&gt; like to be able to do is nest the contract class inside the interface, just like I do with other classes which are tightly coupled to an &amp;quot;owner&amp;quot; type. Then the code would look like this:&lt;/p&gt;  &lt;div class="code"&gt;[ContractClass(&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(ICaseConverterContracts))]     &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; ICaseConverter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text);     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [ContractClassFor(&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(ICaseConverter))]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;internal&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; ICaseConverterContracts : ICaseConverter     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; ICaseConverter.Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Contract.Requires(text != &lt;span class="Keyword"&gt;null&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Contract.Ensures(Contract.Result&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;() != &lt;span class="Keyword"&gt;null&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;default&lt;/span&gt;(&lt;span class="ReferenceType"&gt;string&lt;/span&gt;);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;private&lt;/span&gt; ICaseConverterContracts() {}     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;}     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; InvariantUpperCaseFormatter : ICaseConverter     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;string&lt;/span&gt; Convert(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; text)&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt; text.ToUpperInvariant();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;That would make me feel happier - all the information to do with the interface would be specified within the interface type&amp;#39;s code. It&amp;#39;s possible that with that as a convention, the Code Contracts tooling could cope without the attributes - if interface &lt;code&gt;IFoo&lt;/code&gt; contains a nested class &lt;code&gt;IFooContracts&lt;/code&gt; which implements &lt;code&gt;IFoo&lt;/code&gt;, assume it&amp;#39;s a contract class and handle it appropriately. That would be sweet.&lt;/p&gt;  &lt;p&gt;You know the really galling thing? I&amp;#39;m pretty sure VB &lt;em&gt;does&lt;/em&gt; allow nested types in interfaces...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1736652" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/default.aspx">Wacky Ideas</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category></item><item><title>Generic collections - relegate to an appendix?</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/10/02/generic-collections-relegate-to-an-appendix.aspx</link><pubDate>Fri, 02 Oct 2009 21:00:59 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1729096</guid><dc:creator>skeet</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1729096</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1729096</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/10/02/generic-collections-relegate-to-an-appendix.aspx#comments</comments><description>&lt;p&gt;(I tweeted a brief version of this suggestion and the results have been overwhelmingly positive so far, but I thought it would be worth fleshing out anyway.)&lt;/p&gt;  &lt;p&gt;I&amp;#39;m currently editing chapter 3 of C# in Depth. In the first edition, it&amp;#39;s nearly 48 pages long - the longest in the book, and longer than I want it to be.&lt;/p&gt;  &lt;p&gt;One of the sections in there (only 6 pages, admittedly) is a description of various .NET 2.0 collections. However, it&amp;#39;s mostly comparing them with the nongeneric collections from .NET 1.0, which probably isn&amp;#39;t relevant any more. I suspect my readership has now moved on from &amp;quot;I only know C# 1&amp;quot; to &amp;quot;I&amp;#39;ve used C# 2 and I&amp;#39;m reasonably familiar with the framework, but I want to know the details of the language.&amp;quot;&lt;/p&gt;  &lt;p&gt;I propose moving the collections into an appendix. This will mean:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;I&amp;#39;ll cover all versions of .NET, not just 2.0&lt;/li&gt;    &lt;li&gt;It will all be done in a fairly summary form, like the current appendix. (An appendix doesn&amp;#39;t need as much of a narrative structure as a main chapter, IMO.)&lt;/li&gt;    &lt;li&gt;I&amp;#39;ll cover the interfaces as well as the classes - possibly even with pictures (type hierarchies)!&lt;/li&gt;    &lt;li&gt;Chapter 3 can be a bit slimmer (although I&amp;#39;ve been adding a little bit here and there, so I&amp;#39;m not going to save a massive amount)&lt;/li&gt;    &lt;li&gt;It will be easier to find as a quick reference (and I&amp;#39;ll write it in a way which makes it easy to &lt;em&gt;use&lt;/em&gt; as a reference too, hopefully)&lt;/li&gt;    &lt;li&gt;I don&amp;#39;t have to edit it right now :)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Does this sound like a plan? I don&amp;#39;t know why I didn&amp;#39;t think of it before, but I &lt;em&gt;think&lt;/em&gt; it&amp;#39;s the right move. In particular, it&amp;#39;s in-keeping with the LINQ operator coverage in the existing appendix.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1729096" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Recent activities</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/09/04/recent-activities.aspx</link><pubDate>Thu, 03 Sep 2009 23:08:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1720570</guid><dc:creator>skeet</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1720570</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1720570</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/09/04/recent-activities.aspx#comments</comments><description>&lt;p&gt;It&amp;#39;s been a little while since I&amp;#39;ve blogged, and quite a lot has been going on. In fact, there are a few things I&amp;#39;d have blogged about already if it weren&amp;#39;t for &amp;quot;things&amp;quot; getting in the way.&lt;/p&gt;
&lt;p&gt;Rather than writing a whole series of very short blog posts, I thought I&amp;#39;d wrap them all up here...&lt;/p&gt;
&lt;h3&gt;C# in Depth: next MEAP drop available soon - Code Contracts&lt;/h3&gt;
&lt;p&gt;Thanks to everyone who gave feedback on my &lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2009/08/05/tricky-decisions-code-contracts-and-parallel-extensions-in-c-in-depth-2nd-edition.aspx"&gt;writing dilemma&lt;/a&gt;. For the moment, the plan is to have a whole chapter about Code Contracts, but &lt;em&gt;not&lt;/em&gt; include a chapter about Parallel Extensions. My argument for making this decision is that Code Contracts really change the &lt;em&gt;feel&lt;/em&gt; of the code, making it almost like a language feature - and its applicability is almost ubiquitous, unlike PFX.&lt;/p&gt;
&lt;p&gt;I &lt;em&gt;may&lt;/em&gt; write a PFX chapter as a separate download, but I&amp;#39;m sensitive to those who (like me) appreciate slim books. I don&amp;#39;t want to &amp;quot;bulk out&amp;quot; the book with extra topics.&lt;/p&gt;
&lt;p&gt;The Code Contracts chapter is in the final stages before becoming available to MEAP subscribers. (It&amp;#39;s been &amp;quot;nearly ready&amp;quot; for a couple of weeks, but I&amp;#39;ve been on holiday, amongst other things.) After that, I&amp;#39;m going back to the existing chapters and revising them.&lt;/p&gt;
&lt;h3&gt;Talking in Dublin - C# 4 and Parallel Extensions&lt;/h3&gt;
&lt;p&gt;Last week I gave two talks in Dublin at &lt;a href="http://epicenter.ie/"&gt;Epicenter&lt;/a&gt;. One was on C# 4, and the other on Code Contracts and Parallel Extensions. Both are now available in a slightly odd form on the &lt;a href="http://csharpindepth.com/Talks.aspx"&gt;Talks page&lt;/a&gt; of the C# in Depth web site. I no longer write &amp;quot;formal&amp;quot; PowerPoint slides, so the downloads are for simple bullet points of text, along with silly hand-drawn slides. No code yet - I want to tidy it up a bit before including it.&lt;/p&gt;
&lt;h3&gt;Podcasting with The Connected Show&lt;/h3&gt;
&lt;p&gt;I recently recorded a &lt;a href="http://www.lyalin.com/Blog/archive/2009/09/01/connected-show-15-ndash-c-4-it-ainrsquot-that-complex.aspx"&gt;podcast episode&lt;/a&gt; with &lt;a href="http://www.connectedshow.com/"&gt;The Connected Show&lt;/a&gt;. I&amp;#39;m &amp;quot;on&amp;quot; for the second 2/3 of the show - about an hour of me blathering on about the new features of C# 4. If you can understand generic variance just by listening to me talking about it, you&amp;#39;re a smart cookie ;)&lt;/p&gt;
&lt;p&gt;(Oh, and if you like it, please express your amusement on &lt;a href="http://digg.com/microsoft/Connected_Show_15_Jon_Skeet_goes_DEEP_on_C_4_0"&gt;Digg&lt;/a&gt; / &lt;a href="http://www.dzone.com/links/connected_show_15_jon_skeet_goes_deep_on_c_40.html"&gt;DZone&lt;/a&gt; / &lt;a href="http://dotnetshoutout.com/Connected-Show-15-Jon-Skeet-goes-DEEP-on-C-40"&gt;Shout&lt;/a&gt; / &lt;a href="http://www.dotnetkicks.com/csharp/Connected_Show_15_Jon_Skeet_goes_DEEP_on_C_4_0"&gt;Kicks&lt;/a&gt;.)&lt;/p&gt;
&lt;h3&gt;Finishing up with Functional Programming for the Real World&lt;/h3&gt;
&lt;p&gt;Well, this hasn&amp;#39;t been taking much of my time recently (I bowed out of all the indexing etc!) but &lt;a href="http://manning.com/petricek"&gt;Functional Programming for the Real World&lt;/a&gt; is nearly ready to go. Hard copy should be available in the next couple of months... it&amp;#39;ll be really nice to see how it fares. Much kudos to Tomas for all his hard work - I&amp;#39;ve really just been helping out a little.&lt;/p&gt;
&lt;h3&gt;Starting on Groovy in Action, 2nd edition&lt;/h3&gt;
&lt;p&gt;No sooner does one book finish than another one starts. The &lt;a href="http://manning.com/koenig2/"&gt;second edition of Groovy in Action&lt;/a&gt; is in the works, which should prove interesting. To be honest, I haven&amp;#39;t played with Groovy much since the first edition of the book was finished, so it&amp;#39;ll be interesting to see what&amp;#39;s happened to the language in the meantime. I&amp;#39;ll be applying the same sort of spit and polish that I did in the first edition, and asking appropriately ignorant questions of the other authors.&lt;/p&gt;
&lt;h3&gt;Tech Reviewing C# 4.0 in a Nutshell&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2008/03/31/book-review-c-3-0-in-a-nutshell.aspx"&gt;I liked C# 3.0 in a Nutshell&lt;/a&gt;, and I feel honoured that Joe asked me to be a tech reviewer for the next edition, which promises to be even better. There&amp;#39;s not a lot more I can say about it at the moment, other than it&amp;#39;ll be out in 2010 - and I still feel that C# in Depth is a good companion book.&lt;/p&gt;
&lt;h3&gt;MoreLINQ now at 1.0 beta&lt;/h3&gt;
&lt;p&gt;A while ago I started the &lt;a href="http://code.google.com/p/morelinq/"&gt;MoreLINQ project&lt;/a&gt;, and it gained some developers with more time than I&amp;#39;ve got available :) Basically the idea is to add some more useful LINQ extension methods to LINQ to Object. Thanks to Atif Aziz, the first beta version has been released. This doesn&amp;#39;t mean we&amp;#39;re &amp;quot;done&amp;quot; though - just that we think we&amp;#39;ve got something useful. Any suggestions for other operators would be welcome.&lt;/p&gt;
&lt;h3&gt;Manning Pop Quiz and discounts&lt;/h3&gt;
&lt;p&gt;While I&amp;#39;m plugging books etc, it&amp;#39;s worth mentioning the &lt;a href="http://www.manning.com/popquiz/"&gt;Manning Pop Quiz&lt;/a&gt; - multiple choice questions on a wide variety of topics. Fabulous prizes available, as well as one-day discounts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monday, Sept 7th: 50% of all print books (code: pop0907)&lt;/li&gt;
&lt;li&gt;Monday, Sept 14: 50% off all ebooks&amp;nbsp; (code: pop0914)&lt;/li&gt;
&lt;li&gt;Thursday, Sept 17: $25 for C# in Depth, 2nd Edition MEAP print version (code: pop0917) + C# Pop Quiz question&lt;/li&gt;
&lt;li&gt;Monday, Sept 21: 50% off all books&amp;nbsp; (code: pop0921)&lt;/li&gt;
&lt;li&gt;Thursday, Sept 24: $12 for C# in Depth, 2nd Edition MEAP ebook (code: pop0924) + another C# Pop Quiz question&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Future speaking engagements&lt;/h3&gt;
&lt;p&gt;On September 16th I&amp;#39;m going to be speaking to &lt;a href="http://edgeug.net/"&gt;Edge UG&lt;/a&gt; (formerly Vista Squad) in London about Code Contracts and Parallel Extensions. I&amp;#39;m already &lt;em&gt;very&lt;/em&gt; much looking forward to the &lt;a href="http://stackoverflow.carsonified.com/events/london/"&gt;Stack Overflow DevDays London conference&lt;/a&gt; on October 28th, at which I&amp;#39;ll be talking about how humanity has screwed up computing.&lt;/p&gt;
&lt;h3&gt;Future potential blog posts&lt;/h3&gt;
&lt;p&gt;Some day I may get round to writing about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Revisiting StaticRandom with ThreadLocal&amp;lt;T&amp;gt;&lt;/li&gt;
&lt;li&gt;Volatile doesn&amp;#39;t mean what I thought it did&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&amp;#39;s a lot more writing than coding in that list... I&amp;#39;d like to spend some more time on &lt;a href="http://code.google.com/p/minibench/"&gt;MiniBench&lt;/a&gt; at some point, but you know what deadlines are like.&lt;/p&gt;
&lt;p&gt;Anyway, that&amp;#39;s what I&amp;#39;ve been up to and what I&amp;#39;ll be doing for a little while...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1720570" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/General/default.aspx">General</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Parallelisation/default.aspx">Parallelisation</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Speaking+engagements/default.aspx">Speaking engagements</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Stack+Overflow/default.aspx">Stack Overflow</category></item><item><title>The "dream book" for C# and .NET</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/08/20/the-quot-dream-book-quot-for-c-and-net.aspx</link><pubDate>Thu, 20 Aug 2009 16:57:40 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1716905</guid><dc:creator>skeet</dc:creator><slash:comments>33</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1716905</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1716905</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/08/20/the-quot-dream-book-quot-for-c-and-net.aspx#comments</comments><description>&lt;p&gt;This morning I &lt;a href="http://twitter.com/jonskeet/status/3424128643"&gt;showed my hand a little on Twitter&lt;/a&gt;. I&amp;#39;ve had a dream for a long time about the ultimate C# book. It&amp;#39;s a dream based on &lt;a href="http://www.amazon.com/dp/0321356683"&gt;Effective Java&lt;/a&gt;, which is my favourite Java book, along with my experiences of writing C# in Depth.&lt;/p&gt;  &lt;p&gt;Effective Java is written by Josh Bloch, who is an absolute giant in the Java world... and that&amp;#39;s both the problem and the opportunity. There&amp;#39;s no-one of quite the equivalent stature in the .NET world. Instead, there are many very smart people, a lot of whom blog and some of whom have their own books.&lt;/p&gt;  &lt;p&gt;There are &amp;quot;best practices&amp;quot; books, of course: Microsoft&amp;#39;s own Framework Design Guidelines, and Bill Wagner&amp;#39;s &lt;a href="http://www.amazon.com/dp/0321245660"&gt;Effective C#&lt;/a&gt; and &lt;a href="http://www.amazon.com/dp/0321485890"&gt;More Effective C#&lt;/a&gt; being the most obvious examples. I&amp;#39;m in no way trying to knock these books, but I feel we could do even better. The &lt;a href="http://www.amazon.com/dp/0321246756"&gt;Framework Design Guidelines&lt;/a&gt; (also available &lt;a href="http://msdn.microsoft.com/en-us/library/ms229042.aspx"&gt;free to browse on MSDN&lt;/a&gt;) are really about how to create a good API - which is important, but not the be-all-and-end-all for many &lt;em&gt;application&lt;/em&gt; developers who aren&amp;#39;t trying to ship a reusable class library and may well have different concerns. They want to know how to use the &lt;em&gt;language&lt;/em&gt; most effectively, as well as the core types within the framework.&lt;/p&gt;  &lt;p&gt;Bill&amp;#39;s books - and many others which cover the core framework, such as &lt;a href="http://www.amazon.com/dp/0735621632"&gt;CLR via C#&lt;/a&gt;, &lt;a href="http://www.amazon.com/dp/1590598733"&gt;Accelerated C# 2008&lt;/a&gt; and &lt;a href="http://www.amazon.com/dp/0596527578"&gt;C# 3.0 in a Nutshell&lt;/a&gt; - give plenty of advice, but often I&amp;#39;ve felt it&amp;#39;s a little one-sided. Each of these books is the work of a single person (or brothers in the case of Nutshell). Reading them, I&amp;#39;ve often wanted to give present a different point of view - or alternatively, to give a hearty &amp;quot;hear, hear.&amp;quot; I believe that a book giving guidance would benefit greatly from being more of a conversation: where the authors all agree on something, that&amp;#39;s great; where they differ, it would be good to hear about the pros and cons of various approaches. The reader can then weigh up those factors as they apply to each particular real-world scenario.&lt;/p&gt;  &lt;h2&gt;Scope&lt;/h2&gt;  &lt;p&gt;So what would such a book contain? Opinions will vary of course, but &lt;em&gt;I&lt;/em&gt; would like to see:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Effective ways of using language features such as lambda expressions, generic type inference (and indeed generics in general), optional parameters, named arguments and extension methods. Assume that the reader knows &lt;em&gt;roughly&lt;/em&gt; what C# does, but give some extra details around things like iterator blocks and anonymous functions.&lt;/li&gt;    &lt;li&gt;Guidance around class design (in a similar fashion to the FDG, but with more input from others in the community)&lt;/li&gt;    &lt;li&gt;Core framework topics (again, assume the basics are understood):&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;Resource management (disposal etc)&lt;/li&gt;      &lt;li&gt;Exceptions&lt;/li&gt;      &lt;li&gt;Collections (including LINQ fundamentals)&lt;/li&gt;      &lt;li&gt;Streams&lt;/li&gt;      &lt;li&gt;Text (including internationalization)&lt;/li&gt;      &lt;li&gt;Numeric types&lt;/li&gt;      &lt;li&gt;Time-related APIs&lt;/li&gt;      &lt;li&gt;Concurrency&lt;/li&gt;      &lt;li&gt;Contracts&lt;/li&gt;      &lt;li&gt;AppDomains&lt;/li&gt;      &lt;li&gt;Security&lt;/li&gt;      &lt;li&gt;Performance&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;p&gt;I would prefer to avoid anything around the periphery of .NET (WPF, WinForms, ASP.NET, WCF) - I believe those are better handled in different topics.&lt;/p&gt;  &lt;h2&gt;Obstacles and format&lt;/h2&gt;  &lt;p&gt;There&amp;#39;s one big problem with this idea, but I think it may be a saving grace too. Many of the leading authors work for different publishers. Clearly no single publisher is going to attract &lt;em&gt;all&lt;/em&gt; the best minds in the C# and .NET world. So how could this work in practice? Well...&lt;/p&gt;  &lt;p&gt;Imagine a web site for the book, paid for jointly by all interested publishers. The web site would be the foremost delivery mechanism for the content, both to browse and probably to download in formats appropriate for offline reading (PDF etc). The content would be edited in a collaborative style obviously, but exactly how that would work is a detail to be thrashed out. If you&amp;#39;ve read the annotated C# or CLI specifications, they have about the right feel - opinions can be attributed in places, but not &lt;em&gt;everything&lt;/em&gt; has a label.&lt;/p&gt;  &lt;p&gt;Any contributing publisher could &lt;em&gt;also&lt;/em&gt; take the material and publish it as hard copy if they so wished. Quite how this would work - with potentially multiple hard copy editions of the same content - would be interesting to see. There&amp;#39;s another reason against hard copy ever appearing though, which is that it would be immovable. I&amp;#39;d like to see this work evolve as new features appear and as more best practices are discovered. Publishers could monetize the web site via adverts, possibly according to how much they&amp;#39;re kicking into the site.&lt;/p&gt;  &lt;p&gt;I don&amp;#39;t know how the authors would get paid, admittedly, and that&amp;#39;s another problem. Would this cannibalize the sales of the books listed earlier? It wouldn&amp;#39;t make them redundant - certainly not for the Nutshell type of book, which teaches the basics as well as giving guidance. It would hit Effective C# harder, I suspect - and I apologise to Bill Wagner in advance; if this ever takes off and it hurts his bottom line, I&amp;#39;m very sorry - I think it&amp;#39;s in a good cause though.&lt;/p&gt;  &lt;h2&gt;Dream Team&lt;/h2&gt;  &lt;p&gt;So who would contribute to this? Part of me would like to say &amp;quot;anyone and everyone&amp;quot; in a Wikipedia kind of approach - but I think that practically, it makes sense for industry experts to take their places. (A good feedback/comments mechanism for anyone to use would be crucial, however.) Here&amp;#39;s a list which isn&amp;#39;t meant to be exhaustive, but would make me happy - please don&amp;#39;t take offence if your name isn&amp;#39;t on here but should be, and I wouldn&amp;#39;t expect &lt;em&gt;all&lt;/em&gt; of these people to be interested anyway.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Anders Hejlsberg&lt;/li&gt;    &lt;li&gt;Eric Lippert&lt;/li&gt;    &lt;li&gt;Mads Torgersen&lt;/li&gt;    &lt;li&gt;Don Box&lt;/li&gt;    &lt;li&gt;Brad Abrams&lt;/li&gt;    &lt;li&gt;Krzysztof Cwalina&lt;/li&gt;    &lt;li&gt;Joe Duffy&lt;/li&gt;    &lt;li&gt;Vance Morrison&lt;/li&gt;    &lt;li&gt;Rico Mariani&lt;/li&gt;    &lt;li&gt;Erik Meijer&lt;/li&gt;    &lt;li&gt;Don Symes&lt;/li&gt;    &lt;li&gt;Wes Dyer&lt;/li&gt;    &lt;li&gt;Jeff Richter&lt;/li&gt;    &lt;li&gt;Joe and Ben Albahari&lt;/li&gt;    &lt;li&gt;Andrew Troelsen&lt;/li&gt;    &lt;li&gt;Bill Wagner&lt;/li&gt;    &lt;li&gt;Trey Nash&lt;/li&gt;    &lt;li&gt;Mark Michaelis&lt;/li&gt;    &lt;li&gt;Jon Skeet (yeah, I want to contribute if I can)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I imagine &amp;quot;principal&amp;quot; authors for specific topics (e.g. Joe Duffy for concurrency) but with all the authors dropping in comments in other places too.&lt;/p&gt;  &lt;h2&gt;Dream or reality?&lt;/h2&gt;  &lt;p&gt;I have no idea whether this will ever happen or not. I&amp;#39;d dearly love it to, and I&amp;#39;ve spoken to a few people before today who&amp;#39;ve been encouraging about the idea. I haven&amp;#39;t been putting any work into getting it off the ground - don&amp;#39;t worry, it&amp;#39;s not been delaying the second edition of C# in Depth. One day though, one day...&lt;/p&gt;  &lt;p&gt;Am I being hopelessly naïve to even consider such a venture? Is the scope too broad? Is the content valuable but not money-making? We&amp;#39;ll see.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1716905" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/default.aspx">Wacky Ideas</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Tricky decisions... Code Contracts and Parallel Extensions in C# in Depth 2nd edition</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/08/05/tricky-decisions-code-contracts-and-parallel-extensions-in-c-in-depth-2nd-edition.aspx</link><pubDate>Wed, 05 Aug 2009 16:16:15 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1713522</guid><dc:creator>skeet</dc:creator><slash:comments>83</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1713522</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1713522</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/08/05/tricky-decisions-code-contracts-and-parallel-extensions-in-c-in-depth-2nd-edition.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;d like some feedback from readers, and I suspect my blog is the simplest way to get it.&lt;/p&gt;  &lt;p&gt;I&amp;#39;m currently writing chapter 15 of C# in Depth, tentatively about Code Contracts and Parallel Extensions. The problem is that I&amp;#39;m 15 pages in, and I haven&amp;#39;t finished Code Contracts yet. I suspect that with a typesetter moving the listings around a little it can be shortened a little bit, but I&amp;#39;m still concerned. With the amount I&amp;#39;ve still got to write, Code Contracts is going to end up at 20 pages and I expect Parallel Extensions may be 25. That makes for a pretty monstrous chapter for non-language features.&lt;/p&gt;  &lt;p&gt;I&amp;#39;d like to present a few options:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Keep going as I am, and take the hit of having a big chapter. I&amp;#39;m not going into huge amounts of detail anyway, but the bigger point is to demonstrate how code isn&amp;#39;t what it used to be. We&amp;#39;re no longer writing a simple series of statements to be executed in order. Code Contracts changes this dramatically with the binary rewriter, and Parallel Extensions adjusts the parallelism, and ironically makes it easier to write asynchronous code &lt;em&gt;as if&lt;/em&gt; it were executed sequentially.&lt;/li&gt;    &lt;li&gt;Try to whittle the material down to my original target of around 35 pages. This means it&amp;#39;ll be a really cursory glance at each of the technologies - I&amp;#39;m unsure of how useful it would be at all at that point.&lt;/li&gt;    &lt;li&gt;Don&amp;#39;t even claim to give enough information to really get people going with the new technologies, but possibly introduce extra ones as well, such as &lt;a href="http://www.postsharp.org/"&gt;PostSharp&lt;/a&gt;. Build the theme of &amp;quot;you&amp;#39;re not writing C# 1 any more&amp;quot; in a stronger sense - zoom back to show the bigger picture while ignoring the details.&lt;/li&gt;    &lt;li&gt;Separate them into different chapters. At this point &lt;em&gt;half&lt;/em&gt; the new chapters would be non-language features, which isn&amp;#39;t great for the focus of the book... but at least they&amp;#39;d be a more reasonable size.&lt;/li&gt;    &lt;li&gt;Ditch the chapters from the book completely, possibly writing them as separate chapters to be available as a mini-ebook companion to the book. (We could possibly include them in the ebook version.) This would make the second edition more focused again and possibly give me a bit more space when revising earlier chapters. However, it does mean there&amp;#39;d only be two full-size new chapters for the second edition. (There&amp;#39;ll be a new &amp;quot;wrapping up&amp;quot; chapter as well for a sense of closure, but I&amp;#39;m not generally counting that.)&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Other suggestions are welcome, of course. I&amp;#39;m not going to claim that we&amp;#39;ll end up doing whatever is suggested here, but I&amp;#39;m sure that popular opinion will influence the final decision.&lt;/p&gt;  &lt;p&gt;Thoughts?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1713522" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category></item><item><title>Faking COM to fool the C# compiler</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/07/07/faking-com-to-fool-the-c-compiler.aspx</link><pubDate>Tue, 07 Jul 2009 22:28:46 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698645</guid><dc:creator>skeet</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1698645</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1698645</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/07/07/faking-com-to-fool-the-c-compiler.aspx#comments</comments><description>&lt;p&gt;C# 4 has some great features to make programming against COM components &lt;strike&gt;bearable&lt;/strike&gt; fun and exciting. In particular:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;PIA linking allows you to embed just the relevant bits of the Primary Interop Assembly into your own assembly, so the PIA isn&amp;#39;t actually required at execution time &lt;/li&gt;    &lt;li&gt;Named arguments and optional parameters make life &lt;em&gt;much&lt;/em&gt; simpler for APIs like Office which are full of methods with gazillions of parameters &lt;/li&gt;    &lt;li&gt;&amp;quot;ref&amp;quot; removal allows you to pass an argument by value even though the parameter is a by-reference parameter (COM only, folks - don&amp;#39;t worry!) &lt;/li&gt;    &lt;li&gt;Dynamic typing allows you to remove a load of casts by converting every parameter and return type of &amp;quot;object&amp;quot; into &amp;quot;dynamic&amp;quot; (if you&amp;#39;re using PIA linking) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I&amp;#39;m currently writing about these features for &lt;a href="http://manning.com/skeet2"&gt;the book&lt;/a&gt; (don&amp;#39;t forget to &lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2009/07/06/books-going-cheap.aspx"&gt;buy it cheap on Friday&lt;/a&gt;) but I&amp;#39;m not really a COM person. I want to be able to see these compiler features at work against a really simple type. Unfortunately, these really are COM-specific features... so we&amp;#39;re going to have to persuade COM that the type really is a COM type.&lt;/p&gt;  &lt;p&gt;I got slightly stuck on this first, but thanks to &lt;a href="http://stackoverflow.com/questions/1093536"&gt;the power of Stack Overflow&lt;/a&gt;, I now have a reasonably complete demo &amp;quot;fake&amp;quot; COM type. It doesn&amp;#39;t do a lot, and in particular it doesn&amp;#39;t have any events, but it&amp;#39;s enough to show the compiler features:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;     &lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Runtime.InteropServices;     &lt;br /&gt;    &lt;br /&gt;&lt;span class="InlineComment"&gt;// Required for linking into another assembly (C# 4)&lt;/span&gt;     &lt;br /&gt;[assembly:Guid(&lt;span class="String"&gt;&amp;quot;86ca55e4-9d4b-462b-8ec8-b62e993aeb64&amp;quot;&lt;/span&gt;)]     &lt;br /&gt;[assembly:ImportedFromTypeLib(&lt;span class="String"&gt;&amp;quot;fake.tlb&amp;quot;&lt;/span&gt;)]     &lt;br /&gt;    &lt;br /&gt;&lt;span class="Namespace"&gt;namespace&lt;/span&gt; FakeCom     &lt;br /&gt;{     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Guid(&lt;span class="String"&gt;&amp;quot;c3cb8098-0b8f-4a9a-9772-788d340d6ae0&amp;quot;&lt;/span&gt;)]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [ComImport, CoClass(&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(FakeImpl))]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; FakeComponent     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;object&lt;/span&gt; MakeMeDynamic(&lt;span class="ReferenceType"&gt;object&lt;/span&gt; arg);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;void&lt;/span&gt; Foo([Optional] &lt;span class="MethodParameter"&gt;ref&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;int&lt;/span&gt; x,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [Optional] &lt;span class="MethodParameter"&gt;ref&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;string&lt;/span&gt; y);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }     &lt;br /&gt;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [Guid(&lt;span class="String"&gt;&amp;quot;734e6105-a20f-4748-a7de-2c83d7e91b04&amp;quot;&lt;/span&gt;)]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; FakeImpl {}     &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;We have an interface representing our COM type, and a class which the interface claims will implement it. Fortunately the compiler doesn&amp;#39;t actually check that, so we can get away with leaving it entirely unimplemented. It&amp;#39;s also worth noting that our optional parameters can be by-reference parameters (which you can&amp;#39;t normally do in C# 4) and we haven&amp;#39;t given them any default values (as those are ignored for COM anyway).&lt;/p&gt;  &lt;p&gt;This is compiled just like any other assembly: &lt;/p&gt;  &lt;div class="code"&gt;csc /target:library FakeCom.cs &lt;/div&gt;  &lt;p&gt;Then we get to use it with a test program: &lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; FakeCom;    &lt;br /&gt;    &lt;br /&gt;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Test    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Yes, that is calling a &amp;quot;constructor&amp;quot; on an interface&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; FakeComponent com = &lt;span class="Keyword"&gt;new&lt;/span&gt; FakeComponent();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// The boring old fashioned way of calling a method&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; i = 0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; j = &lt;span class="Keyword"&gt;null&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; com.Foo(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; i, &lt;span class="MethodParameter"&gt;ref&lt;/span&gt; j);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Look ma, no ref!&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; com.Foo(10, &lt;span class="String"&gt;&amp;quot;Wow!&amp;quot;&lt;/span&gt;);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Who cares about parameter ordering?&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; com.Foo(y: &lt;span class="String"&gt;&amp;quot;Not me&amp;quot;&lt;/span&gt;, x: 0);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// And the parameters are optional too&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; com.Foo();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// The line below only works when linked rather than&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// referenced, as otherwise you need a cast.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// The compiler treats it as if it both takes and&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// returns a dynamic value.&lt;/span&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; value = com.MakeMeDynamic(10);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;This is compiled either in the old &amp;quot;deploy the PIA as well&amp;quot; way (after adding a cast in the last line): &lt;/p&gt;  &lt;div class="code"&gt;csc /r:FakeCom.dll Test.cs &lt;/div&gt;  &lt;p&gt;... or by linking the PIA instead:&lt;/p&gt;  &lt;div class="code"&gt;csc /l:FakeCom.dll Test.cs &lt;/div&gt;  &lt;p&gt;(The difference is just using &lt;code&gt;/l&lt;/code&gt; instead of &lt;code&gt;/r&lt;/code&gt;.)&lt;/p&gt;  &lt;p&gt;When the test code is compiled as a reference, it decompiles in Reflector to this (I&amp;#39;ve added whitespace for clarity):&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; FakeComponent component = (FakeComponent) &lt;span class="Keyword"&gt;new&lt;/span&gt; FakeImpl();    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; x = 0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; y = &lt;span class="Keyword"&gt;null&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; component.Foo(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; x, &lt;span class="MethodParameter"&gt;ref&lt;/span&gt; y);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; num2 = 10;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; str3 = &lt;span class="String"&gt;&amp;quot;Wow!&amp;quot;&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; component.Foo(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; num2, &lt;span class="MethodParameter"&gt;ref&lt;/span&gt; str3);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; str4 = &lt;span class="String"&gt;&amp;quot;Not me&amp;quot;&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; num3 = 0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; component.Foo(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; num3, &lt;span class="MethodParameter"&gt;ref&lt;/span&gt; str4);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;int&lt;/span&gt; num4 = 0;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; str5 = &lt;span class="Keyword"&gt;null&lt;/span&gt;;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; component.Foo(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; num4, &lt;span class="MethodParameter"&gt;ref&lt;/span&gt; str5);    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; str2 = (&lt;span class="ReferenceType"&gt;string&lt;/span&gt;) component.MakeMeDynamic(10);    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Note how the compiler has created local variables to pass by reference; any changes to the parameter are ignored when the method returns. (If you actually pass a variable by reference, the compiler won&amp;#39;t take that away, however.) &lt;/p&gt;  &lt;p&gt;When the code is linked instead, the middle section is the same, but the construction and the line calling &lt;code&gt;MakeMeDynamic&lt;/code&gt; are very different:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;private&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; FakeComponent component = (FakeComponent) Activator.CreateInstance(Type.GetTypeFromCLSID    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&lt;span class="Keyword"&gt;new&lt;/span&gt; Guid(&lt;span class="String"&gt;&amp;quot;734E6105-A20F-4748-A7DE-2C83D7E91B04&amp;quot;&lt;/span&gt;)));    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="InlineComment"&gt;// Middle bit as before&lt;/span&gt;    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;if&lt;/span&gt; (&amp;lt;Main&amp;gt;o__SiteContainer6.&amp;lt;&amp;gt;p__Site7 == &lt;span class="Keyword"&gt;null&lt;/span&gt;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Main&amp;gt;o__SiteContainer6.&amp;lt;&amp;gt;p__Site7 = CallSite&amp;lt;Func&amp;lt;CallSite, &lt;span class="ReferenceType"&gt;object&lt;/span&gt;, &lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; .Create(&lt;span class="Keyword"&gt;new&lt;/span&gt; CSharpConvertBinder    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&lt;span class="Keyword"&gt;typeof&lt;/span&gt;(&lt;span class="ReferenceType"&gt;string&lt;/span&gt;),&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CSharpConversionKind.ImplicitConversion, &lt;span class="Keyword"&gt;false&lt;/span&gt;));    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; str2 = &amp;lt;Main&amp;gt;o__SiteContainer6.&amp;lt;&amp;gt;p__Site7.Target.Invoke    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;lt;Main&amp;gt;o__SiteContainer6.&amp;lt;&amp;gt;p__Site7, component.MakeMeDynamic(10));    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;The interface is embedded in the generated assembly, but with a slightly different set of attributes:&lt;/p&gt;  &lt;div class="code"&gt;[ComImport, CompilerGenerated]   &lt;br /&gt;[Guid(&lt;span class="String"&gt;&amp;quot;C3CB8098-0B8F-4A9A-9772-788D340D6AE0&amp;quot;&lt;/span&gt;), TypeIdentifier]    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;interface&lt;/span&gt; FakeComponent    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ReferenceType"&gt;object&lt;/span&gt; MakeMeDynamic(&lt;span class="ReferenceType"&gt;object&lt;/span&gt; arg);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="ValueType"&gt;void&lt;/span&gt; Foo([Optional] &lt;span class="MethodParameter"&gt;ref&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;int&lt;/span&gt; x, [Optional] &lt;span class="MethodParameter"&gt;ref&lt;/span&gt;&amp;#160;&lt;span class="ReferenceType"&gt;string&lt;/span&gt; y);    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;The class isn&amp;#39;t present at all.&lt;/p&gt;  &lt;p&gt;I should point out that doing this has no practical benefit in real code - but the ability to mess around with a pseudo-COM type rather than having to find a &lt;em&gt;real&lt;/em&gt; one with the exact members I want will make it a lot easier to try a few corner cases for the book.&lt;/p&gt;  &lt;p&gt;So, not a terribly productive evening in terms of getting actual writing done, but interesting nonetheless...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698645" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Wacky+Ideas/default.aspx">Wacky Ideas</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Stack+Overflow/default.aspx">Stack Overflow</category></item><item><title>Books going cheap</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/07/06/books-going-cheap.aspx</link><pubDate>Mon, 06 Jul 2009 16:06:16 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1698425</guid><dc:creator>skeet</dc:creator><slash:comments>20</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1698425</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1698425</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/07/06/books-going-cheap.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m delighted to say that Manning is having a promotional week, with a one-day discount voucher on each of the books I&amp;#39;ve been working on. Here&amp;#39;s the list of what&amp;#39;s going cheap when:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Tuesday July 7th: &lt;a href="http://manning.com/skeet"&gt;C# in Depth, 1st edition&lt;/a&gt; - 50% off with code &lt;strong&gt;twtr0708&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Wednesday July 8th: &lt;a href="http://manning.com/koenig2"&gt;Groovy in Action, 2nd edition&lt;/a&gt; - 50% off with code &lt;strong&gt;twtr0709&lt;/strong&gt; (includes ebook of 1st edition)&lt;/li&gt;    &lt;li&gt;Thursday July 9th: &lt;a href="http://manning.com/petricek"&gt;Functional Programming for the Real World&lt;/a&gt; - 50% off with code &lt;strong&gt;twtr0710&lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;Friday July 10th: &lt;a href="http://manning.com/skeet2"&gt;C# in Depth, 2nd edition&lt;/a&gt; - 50% off with code &lt;strong&gt;twtr0711&lt;/strong&gt; (includes ebook of 1st edition)&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This seems an appropriate time to mention that the first new content from the 2nd edition of C# in Depth became available under MEAP over the weekend. I&amp;#39;m looking forward to getting feedback on it.&lt;/p&gt;  &lt;p&gt;I&amp;#39;ll be tweeting the relevant code each morning as well. Go nuts :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1698425" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Dynamic type inference and surprising possibilities</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/06/17/dynamic-type-inference-and-surprising-possibilities.aspx</link><pubDate>Wed, 17 Jun 2009 20:01:13 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1695727</guid><dc:creator>skeet</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1695727</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1695727</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/06/17/dynamic-type-inference-and-surprising-possibilities.aspx#comments</comments><description>&lt;p&gt;There have been mutterings about the fact that I haven&amp;#39;t been blogging much recently. I&amp;#39;ve been getting down to serious work on the second edition of C# in Depth, and it&amp;#39;s taking a lot of my time. However, I thought I&amp;#39;d share a ghastly little example I&amp;#39;ve just come up with.&lt;/p&gt;  &lt;p&gt;I&amp;#39;ve been having an email discussion with &lt;a href="http://blogs.msdn.com/samng/"&gt;Sam Ng&lt;/a&gt;, &lt;a href="http://blogs.msdn.com/cburrows/"&gt;Chris Burrows&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/ericlippert/"&gt;Eric Lippert&lt;/a&gt; about how dynamic typing works. Sam mentioned that even for dynamically bound calls, type inference can fail at compile time. This can only happen for type parameters where none of the dynamic values contribute to the type inference. For example, this fails to compile:&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Execute&amp;lt;T&amp;gt;(T item, &lt;span class="ValueType"&gt;int&lt;/span&gt; value) &lt;span class="Linq"&gt;where&lt;/span&gt; T : &lt;span class="ValueType"&gt;struct&lt;/span&gt; {}     &lt;br /&gt;...     &lt;br /&gt;&lt;span class="Keyword"&gt;dynamic&lt;/span&gt; guid = Guid.NewGuid();     &lt;br /&gt;Execute(&lt;span class="String"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, guid); &lt;/div&gt;  &lt;p&gt;Whatever the value of &lt;code&gt;guid&lt;/code&gt; is at execution time, this can&amp;#39;t &lt;i&gt;possibly&lt;/i&gt; manage to infer a valid type argument for &lt;code&gt;T&lt;/code&gt;. The only type which can be inferred is &lt;code&gt;string&lt;/code&gt;, and that&amp;#39;s not a value type. Fair enough... but what about this one?&lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Execute&amp;lt;T&amp;gt;(T first, T second, T third) &lt;span class="Linq"&gt;where&lt;/span&gt; T : &lt;span class="ValueType"&gt;struct&lt;/span&gt; {}    &lt;br /&gt;...    &lt;br /&gt;&lt;span class="Keyword"&gt;dynamic&lt;/span&gt; guid = Guid.NewGuid();    &lt;br /&gt;Execute(10, 0, guid);    &lt;br /&gt;Execute(10, &lt;span class="Keyword"&gt;false&lt;/span&gt;, guid);    &lt;br /&gt;Execute(&lt;span class="String"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;, &lt;span class="String"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;, guid); &lt;/div&gt;  &lt;p&gt;I expected the first call to compile (but fail at execution time) and the second and third calls to fail at compile time. After all, &lt;code&gt;T&lt;/code&gt; couldn&amp;#39;t be both an &lt;code&gt;int&lt;/code&gt; &lt;i&gt;and&lt;/i&gt; a &lt;code&gt;bool&lt;/code&gt; could it? And then I remembered implicit typing... what if the vaue of &lt;code&gt;guid&lt;/code&gt; isn&amp;#39;t actually a &lt;code&gt;Guid&lt;/code&gt;, but some struct which has an implicit conversion from &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;bool&lt;/code&gt; and &lt;code&gt;string&lt;/code&gt;? In other words, what if the full code actually looked like this: &lt;/p&gt;  &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;    &lt;br /&gt;    &lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;struct&lt;/span&gt; Foo    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;implicit&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;operator&lt;/span&gt; Foo(&lt;span class="ValueType"&gt;int&lt;/span&gt; x)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; Foo();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;implicit&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;operator&lt;/span&gt; Foo(&lt;span class="ValueType"&gt;bool&lt;/span&gt; x)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; Foo();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;#160;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;implicit&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;operator&lt;/span&gt; Foo(&lt;span class="ReferenceType"&gt;string&lt;/span&gt; x)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Statement"&gt;return&lt;/span&gt;&amp;#160;&lt;span class="Keyword"&gt;new&lt;/span&gt; Foo();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;}    &lt;br /&gt;    &lt;br /&gt;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Test    &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Execute&amp;lt;T&amp;gt;(T first, T second, T third) &lt;span class="Linq"&gt;where&lt;/span&gt; T : &lt;span class="ValueType"&gt;struct&lt;/span&gt; {}    &lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;#160;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;span class="Keyword"&gt;dynamic&lt;/span&gt; foo = &lt;span class="Keyword"&gt;new&lt;/span&gt; Foo();    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Execute(10, 0, foo);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Execute(10, &lt;span class="Keyword"&gt;false&lt;/span&gt;, foo);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Execute(&lt;span class="String"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;, &lt;span class="String"&gt;&amp;quot;hello&amp;quot;&lt;/span&gt;, foo);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/div&gt;  &lt;p&gt;Then &lt;code&gt;T=Foo&lt;/code&gt; is a perfectly valid inference. So yes, it all compiles - and the C# binders even get it all right at execution time. So much for any intuition I might have about dynamic typing and inference... &lt;/p&gt;  &lt;p&gt;No doubt I&amp;#39;ll have similar posts about new C# 4 features occasionally... but they&amp;#39;re more likely to be explanations of misunderstandings than deep insights into a &lt;i&gt;correct&lt;/i&gt; view of the language. Those end up in the book instead :) &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1695727" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category></item><item><title>RFC: C# in Depth 2nd edition, proposed changes and additions</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/04/16/rfc-c-in-depth-2nd-edition-proposed-changes-and-additions.aspx</link><pubDate>Thu, 16 Apr 2009 15:54:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1688146</guid><dc:creator>skeet</dc:creator><slash:comments>45</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1688146</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1688146</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/04/16/rfc-c-in-depth-2nd-edition-proposed-changes-and-additions.aspx#comments</comments><description>&lt;p&gt;As I&amp;#39;ve mentioned in passing before now, I&amp;#39;ve started working on the 2nd edition of C# in Depth, to roughly coincide with the release of C# 4 and Visual Studio 2010. So far I&amp;#39;ve just been thinking about what should be added and what should be changed or removed. That&amp;#39;s what I&amp;#39;d like to share today, and I&amp;#39;m &lt;i&gt;really&lt;/i&gt; eager for feedback. In particular, I&amp;#39;d like to think of three audiences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers (possibly hobbyists) who have read one introductory C# book (Head First C#, Microsoft Visual C# 2008 Step by Step or something similar) and are now looking to follow it up. I&amp;#39;m thinking of people with less than a year of full-time development in C#, and not a lot of experience in similar languages. Is C# in Depth too &amp;quot;hard&amp;quot; for this audience? If so, should I &lt;i&gt;try&lt;/i&gt; to make it more accessible for them, or is the material inherently too advanced? What might attract such a person to the book in terms of the table of contents? &lt;/li&gt;
&lt;li&gt;Reasonably experienced developers who know C# 2 and 3 already, but haven&amp;#39;t read C# in Depth. They may have heard of it before (I&amp;#39;ve been very pleased in terms of word-of-mouth for the first edition, so thanks to everyone who&amp;#39;s contributed to that!) but not had much real reason to buy another book when they already have something like C# 3.0 in a Nutshell. Now that C# 4 is around, they may be interested in buying something which will explain the new features, and they might as well get a &lt;i&gt;different&lt;/i&gt; book rather than just a fresh edition of something they already own. &lt;/li&gt;
&lt;li&gt;Existing readers of C# in Depth. If you already own the first edition, what might persuade you to buy the second edition? How much &amp;quot;new&amp;quot; stuff is required? Would you rather get &amp;quot;more bang for the buck&amp;quot; from a significantly thicker book, or does the relative slimness of C# in Depth hold real appeal? (I know I&amp;#39;m a fan of slim books, but I don&amp;#39;t know quite how important it is. The second edition certainly &lt;i&gt;will&lt;/i&gt; be thicker than the first as I&amp;#39;m unlikely to remove much, but I&amp;#39;m sure there&amp;#39;s scope for varying just how much we add.) &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;#39;s a draft table of contents - only down to headings within a chapter, but with some notes. Changes and notes are highlighted &lt;span style="color:#0000ff;"&gt;in blue&lt;/span&gt;.&lt;/p&gt;
&lt;h2&gt;Part 1: Preparing for the journey&lt;/h2&gt;
&lt;h5&gt;Chapter 1: The changing face of C# development&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Evolution in action: examples of code change      &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;I won&amp;#39;t be able to include the C# 4 features by just evolving the existing code... at least, not the big ones. Options:&lt;/span&gt;       
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Stick with the existing example for 1 to 2 and 2 to 3, but change to a different problem for 4&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Try to work out a different example to show all of 1 to 2, 2 to 3 and 3 to 4&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Stick with the existing example, but take it in a different direction for 4, rather than just rewriting the existing code&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A brief history of C# (and related technologies)      &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Update this with what&amp;#39;s been happening since 2008 and possibly slim down what&amp;#39;s already there&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;The .NET platform         &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Add the new versions, including .NET 3.5 SP1, and introduce the DLR in the terminology part.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Fully functional code in snippet form&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Nothing new to add about Snippy, but there &lt;i&gt;may&lt;/i&gt; be another tool to talk about as well.&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 2: Core foundations: building on C# 1&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Delegates &lt;/li&gt;
&lt;li&gt;Type system characteristics &lt;/li&gt;
&lt;li&gt;Value types and reference types &lt;/li&gt;
&lt;li&gt;Beyond C# 1: new features on a solid base      &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Introduce interface/delegate variance and the &lt;code&gt;dynamic&lt;/code&gt; type.&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Part 2: Solving the issues of C# 1&lt;/h2&gt;
&lt;h3&gt;Chapter 3: Parameterized typing with generics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Why generics are necessary&lt;/li&gt;
&lt;li&gt;Simple generics for everyday use&lt;/li&gt;
&lt;li&gt;Beyond the basics     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Add a tip and example about using generic static methods in a non-generic type to take advantage of type inference when creating instances of generic types.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Advanced generics&lt;/li&gt;
&lt;li&gt;Generic collection classes     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;It would probably make sense to include HashSet&amp;lt;T&amp;gt; here, and possibly any new collection classes in .NET 4.0. Version warnings would be given, of course!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Limitations of generics in C# and other languages     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Refer to part 4 in terms of variance, and possibly trim down the coverage of alternative approaches.       &lt;br /&gt;Add an example of Marc Gravell&amp;#39;s work for generic operators, or at least refer to it. Possibly mention the idea of &lt;/span&gt;&lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2008/08/29/lessons-learned-from-protocol-buffers-part-4-static-interfaces.aspx"&gt;&lt;span style="color:#0000ff;"&gt;static interfaces&lt;/span&gt;&lt;/a&gt;&lt;span style="color:#0000ff;"&gt;. Both give food for thought, but aren&amp;#39;t really part of C#.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 4: Saying nothing with nullable types&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;What do you do when you just don&amp;#39;t have a value?&lt;/li&gt;
&lt;li&gt;System.Nullable&amp;lt;T&amp;gt; and System.Nullable&lt;/li&gt;
&lt;li&gt;C# 2&amp;#39;s syntactic sugar for nullable types&lt;/li&gt;
&lt;li&gt;Novel uses of nullable types     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Possibly include Marc Gravell&amp;#39;s teaser about calling all the Object methods on a null value.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Summary     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Make sure the summary is typeset as 4.5 instead of as part of 4.4. Oops!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 5: Fast-tracked delegates&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Saying goodbye to awkward delegate syntax&lt;/li&gt;
&lt;li&gt;Method group conversions&lt;/li&gt;
&lt;li&gt;Covariance and contravariance     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Mention generic delegate variance in C# 4, referring to part 4.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Inline delegate actions with anonymous methods&lt;/li&gt;
&lt;li&gt;Capturing variables in anonymous methods&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 6: Implementing iterators the easy way&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;C# 1: the pain of handwritten iterators&lt;/li&gt;
&lt;li&gt;C# 2: simple iterators with yield statements&lt;/li&gt;
&lt;li&gt;Iteration in the real world     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Renamed section, but keep first example - possibly make it shorter.       &lt;br /&gt;Add iteration over lines in a file.        &lt;br /&gt;Add generation iterator, referring to LINQ.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Pseudo-synchronous code with the Concurrency and Coordination Runtime     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Fix sample code and explanation, with full article on the web&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 7: Concluding C# 2: the final features&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Partial types&lt;/li&gt;
&lt;li&gt;Static classes&lt;/li&gt;
&lt;li&gt;Separate getter/setter property access&lt;/li&gt;
&lt;li&gt;Namespace aliases&lt;/li&gt;
&lt;li&gt;Pragma directives&lt;/li&gt;
&lt;li&gt;Fixed-size buffers in unsafe code&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Part 3: New title TBD&lt;/h2&gt;
&lt;h5&gt;Chapter 8: Cutting fluff with a smart compiler&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Automatically implemented properties&lt;/li&gt;
&lt;li&gt;Implicit typing of local variables&lt;/li&gt;
&lt;li&gt;Simplified initialization&lt;/li&gt;
&lt;li&gt;Implicitly typed arrays&lt;/li&gt;
&lt;li&gt;Anonymous types&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 9: Lambda expressions and expression trees&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Lambda expressions as delegates&lt;/li&gt;
&lt;li&gt;Simple examples using List&amp;lt;T&amp;gt; and events&lt;/li&gt;
&lt;li&gt;Expression trees     &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Expand for new expression support in .NET 4.0 (clearly labeled as such)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Changes to type inference and overload resolution&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Check if/how this has changed in C# 4.0 spec&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5&gt;Chapter 10: Extension methods&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;Life before extension methods&lt;/li&gt;
&lt;li&gt;Extension method syntax&lt;/li&gt;
&lt;li&gt;Extension methods in .NET 3.5&lt;/li&gt;
&lt;li&gt;Usage idea and guidelines       &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Update advice here and give some more examples.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 11: Query expressions and LINQ to Objects&lt;/h5&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;Look at changing how the diagrams are formatted in this chapter.&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introducing LINQ&lt;/li&gt;
&lt;li&gt;Simple beginnings: selecting elements&lt;/li&gt;
&lt;li&gt;Filtering and ordering a sequence&lt;/li&gt;
&lt;li&gt;Let clauses and transparent identifiers&lt;/li&gt;
&lt;li&gt;Joins&lt;/li&gt;
&lt;li&gt;Groupings and continuations&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;New section: extending LINQ to Objects&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Advice for writing your own extension methods&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Plug for MoreLINQ and other libraries&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Chapter 12: LINQ beyond collections&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;LINQ to SQL       &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Despite the rumours of its doom, I think this is the best place to start.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Translations using IQueryable and IQueryProvider&lt;/li&gt;
&lt;li&gt;LINQ to DataSet&lt;/li&gt;
&lt;li&gt;LINQ to XML&lt;/li&gt;
&lt;li&gt;LINQ to Entities       &lt;br /&gt;&lt;span style="color:#0000ff;"&gt;Again, not much depth - still a whirlwind tour.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Third-party LINQ (renamed from LINQ beyond .NET 3.5)&lt;/span&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Update state of play with third-party providers&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Example of PushLINQ - still using simple delegates, but against different interface&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Remove Parallel Extensions - moved to part 4&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;span style="color:#0000ff;"&gt;Chapter 13: Removed (new chapter at end of part 4)&lt;/span&gt;&lt;/h5&gt;
&lt;h2&gt;Part 4: C# 4 (full title TBD)&lt;/h2&gt;
&lt;h5&gt;&lt;span style="color:#0000ff;"&gt;Chapter 13: Dynamic binding in a static language&lt;/span&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Introduction to the DLR, IronPython, IronRuby&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Calling dynamically &amp;ndash; the dynamic keyword&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Reacting dynamically &amp;ndash; implementing IDynamicObject&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Applications for dynamic code&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Summary&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;span style="color:#0000ff;"&gt;Chapter 14: More minor tweaks&lt;/span&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Named and optional arguments&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Variance of interfaces and generic delegates&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Simplifying COM interoperability&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Summary&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;span style="color:#0000ff;"&gt;Chapter 15: Major new features of .NET 4.0&lt;/span&gt;&lt;/h5&gt;
&lt;p&gt;&lt;span style="color:#0000ff;"&gt;Even though these don&amp;#39;t affect the language directly, they change the &amp;quot;shape&amp;quot; of code, the way we think about problems. I&amp;#39;m hoping there will be more...&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Bullet-proofing your code with Code Contracts&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Simplifying concurrency with Parallel Extensions&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;F# (?)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Summary&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;span style="color:#0000ff;"&gt;Chapter 16: Whither now?&lt;/span&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Educated guesses about C# 5&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;The Renaissance developer&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="color:#0000ff;"&gt;Until we meet again&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Appendix: LINQ standard query operators&lt;/h5&gt;
&lt;p&gt;So, how does that sound? What else needs changing from the first edition? Are there any particular sections which would benefit from a neat example? Have I missed anything important that you&amp;#39;d want to see in part 4?&lt;/p&gt;
&lt;p&gt;Right now I&amp;#39;ve got a lot of flexibility - so please, I&amp;#39;d &lt;i&gt;much&lt;/i&gt; rather hear ideas now than later.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1688146" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Current book project: Real World Functional Programming</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/02/27/current-book-project-real-world-functional-programming.aspx</link><pubDate>Fri, 27 Feb 2009 17:44:44 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1674539</guid><dc:creator>skeet</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1674539</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1674539</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/02/27/current-book-project-real-world-functional-programming.aspx#comments</comments><description>&lt;p&gt;Now that it&amp;#39;s all official, I can reveal that since the tail end of last year I&amp;#39;ve been helping out with &lt;a href="http://manning.com/petricek"&gt;Real World Functional Programming&lt;/a&gt; by &lt;a href="http://tomasp.net/"&gt;Tomáš Petříček&lt;/a&gt; (and me, ish).&lt;/p&gt; &lt;p&gt;I&amp;#39;m doing the same kinds of things I did with &lt;a href="http://manning.com/koenig"&gt;Groovy in Action&lt;/a&gt;, coming to the text with fresh eyes: I&amp;#39;m technically competent but don&amp;#39;t have any expertise in the subject matter. This means I can see it as a &amp;quot;real&amp;quot; reader would, challenge the assumptions, point out places which need more explanation etc. I&amp;#39;m also polishing the language a bit and adding a few informative notes. I suspect by the end there won&amp;#39;t be a single paragraph that I&amp;#39;ve written in its entirety, but there&amp;#39;ll also be few paragraphs which I haven&amp;#39;t touched at all.&lt;/p&gt; &lt;p&gt;It&amp;#39;s exciting to get a chance to work on the book, and I hope I&amp;#39;m improving it. Check it out, join the MEAP, and give us feedback :)&lt;/p&gt; &lt;p&gt;I have a couple of other books on the back-burner at the moment too; hopefully I&amp;#39;ll be able to give more details reasonably soon.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1674539" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>New version of Data Structures and Algorithms book now online</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/12/22/new-version-of-data-structures-and-algorithms-book-now-online.aspx</link><pubDate>Mon, 22 Dec 2008 16:59:16 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1657459</guid><dc:creator>skeet</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1657459</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1657459</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/12/22/new-version-of-data-structures-and-algorithms-book-now-online.aspx#comments</comments><description>&lt;p&gt;Some of you may remember an &lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2008/08/29/data-structures-and-algorithms-new-free-ebook-available-first-draft.aspx"&gt;earlier post&lt;/a&gt; about a free Data Structures and Algorithms book which I&amp;#39;m occasionally helping out with in terms of editing.&lt;/p&gt; &lt;p&gt;I&amp;#39;ve just been told that a &lt;a href="http://dotnetslackers.com/projects/Data-Structures-And-Algorithms/"&gt;new version has recently been uploaded&lt;/a&gt; - please check it out. I have to admit that I haven&amp;#39;t actually done any work on this for a while... maybe I&amp;#39;ll get round to it in the New Year. Happy Christmas reading :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1657459" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>The Snippy Reflector add-in</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/11/23/the-snippy-reflector-add-in.aspx</link><pubDate>Sun, 23 Nov 2008 10:25:53 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1654846</guid><dc:creator>skeet</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1654846</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1654846</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/11/23/the-snippy-reflector-add-in.aspx#comments</comments><description>&lt;p&gt;Those of you who&amp;#39;ve read C# in Depth will know about Snippy - a little tool which makes it easy to build complete programs from small snippets of code.&lt;/p&gt; &lt;p&gt;I&amp;#39;m delighted to say that reader &lt;a href="http://jasonhaley.com"&gt;Jason Haley&lt;/a&gt; has taken the &lt;a href="http://csharpindepth.com/Downloads.aspx"&gt;source code for Snippy&lt;/a&gt; and built an add-in for &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt;. This will make it &lt;em&gt;much&lt;/em&gt; simpler to answer questions like &lt;a href="http://stackoverflow.com/questions/203695/structure-vs-class-in-c"&gt;this one about struct initialization&lt;/a&gt;, where you really want to the IL generated for a snippet. Here&amp;#39;s a screenshot to show what it does:&lt;/p&gt; &lt;p&gt;&lt;img src="http://pobox.com/~skeet/csharp/blogfiles/SnippyReflector.png" alt="" /&gt;&lt;/p&gt; &lt;p&gt;This is really cool - if you want to dabble to see what the C# compiler does in particular situations, check it out. It comes as &lt;a href="http://jasonhaley.com/files/Reflector.Snippy.dll"&gt;just the DLL&lt;/a&gt;, or a &lt;a href="http://jasonhaley.com/files/Reflector.Snippy.zip"&gt;zipped version&lt;/a&gt;. Thanks for putting in all this work, Jason :) &lt;p&gt;Update: Jason now has his own (more detailed) &lt;a href="http://jasonhaley.com/blog/archive/2008/11/23/142521.aspx"&gt;blog entry&lt;/a&gt; too.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1654846" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/CSharpDevCenter/default.aspx">CSharpDevCenter</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/CSharpDev/default.aspx">CSharpDev</category></item><item><title>Why boxing doesn't keep me awake at nights</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/10/08/why-boxing-doesn-t-keep-me-awake-at-nights.aspx</link><pubDate>Wed, 08 Oct 2008 19:42:02 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1650177</guid><dc:creator>skeet</dc:creator><slash:comments>26</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1650177</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1650177</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/10/08/why-boxing-doesn-t-keep-me-awake-at-nights.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m currently reading the (generally excellent) &lt;a href="http://www.amazon.com/CLR-via-Second-Pro-Developer/dp/0735621632"&gt;CLR via C#&lt;/a&gt;, and I&amp;#39;ve recently hit the section on boxing. Why is it that authors feel they have to scaremonger about the effects boxing can have on performance?&lt;/p&gt; &lt;p&gt;Here&amp;#39;s a piece of code from the book:&lt;/p&gt; &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;sealed&lt;/span&gt;&amp;nbsp;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Program {&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main() {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Int32 v = 5;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// Create an unboxed value type variable.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#if INEFFICIENT&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// When compiling the following line, v is boxed&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// three times, wasting time and memory&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0}, {1}, {2}&amp;quot;&lt;/span&gt;, v, v, v);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#else&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// The lines below have the same result, execute&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// much faster, and use less memory&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Object o = v;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="InlineComment"&gt;// No boxing occurs to compile the following line.&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0}, {1}, {2}&amp;quot;&lt;/span&gt;, o, o, o);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#endif&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt; &lt;p&gt;In the text afterwards, he reiterates the point: &lt;/p&gt; &lt;blockquote&gt;This second version executes &lt;i&gt;much&lt;/i&gt; faster and allocates less memory from the heap. &lt;/blockquote&gt; &lt;p&gt;This seemed like an overstatement to me, so I thought I&amp;#39;d try it out. Here&amp;#39;s my test application: &lt;/p&gt; &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Diagnostics;&lt;br /&gt;&lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Test&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;const&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;int&lt;/span&gt; Iterations = 10000000;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Stopwatch sw = Stopwatch.StartNew();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;for&lt;/span&gt; (&lt;span class="ValueType"&gt;int&lt;/span&gt; i=0; i &amp;lt; Iterations; i++)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#if&lt;/span&gt; CONSOLE_WITH_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, i, i, i);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; CONSOLE_NO_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;object&lt;/span&gt; o = i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, o, o, o);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; CONSOLE_STRINGS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; s = i.ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, s, s, s);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; FORMAT_WITH_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Format(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, i, i, i);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; FORMAT_NO_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;object&lt;/span&gt; o = i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Format(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, o, o, o);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; FORMAT_STRINGS&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; s = i.ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Format(&lt;span class="String"&gt;&amp;quot;{0} {1} {2}&amp;quot;&lt;/span&gt;, s, s, s);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; CONCAT_WITH_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Concat(i, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, i, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, i);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; CONCAT_NO_BOXING&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;object&lt;/span&gt; o = i;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Concat(o, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, o, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, o);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#elif&lt;/span&gt; CONCAT_STRINGS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt; s = i.ToString();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Concat(s, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, s, &lt;span class="String"&gt;&amp;quot; &amp;quot;&lt;/span&gt;, s);&lt;br /&gt;&lt;span class="PreProcessorDirective"&gt;#endif&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sw.Stop();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.Error.WriteLine(&lt;span class="String"&gt;&amp;quot;{0}ms&amp;quot;&lt;/span&gt;, sw.ElapsedMilliseconds);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt; &lt;p&gt;I compiled the code with one symbol defined each time, with optimisations and without debug information, and ran it from a command line, writing to &lt;code&gt;nul&lt;/code&gt; (i.e. no disk or actual console activity). Here are the results: &lt;/p&gt; &lt;table&gt;  &lt;tr&gt; &lt;th&gt;Symbol&lt;/th&gt; &lt;th&gt;Results (ms)&lt;/th&gt; &lt;th&gt;Average (ms)&lt;/th&gt;&lt;/tr&gt;  &lt;tr&gt; &lt;td&gt;CONSOLE_WITH_BOXING&lt;/td&gt; &lt;td align="right"&gt;33054&lt;/td&gt; &lt;td align="right"&gt;33444&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;33898&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;33381&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;CONSOLE_NO_BOXING&lt;/td&gt; &lt;td align="right"&gt;34638&lt;/td&gt; &lt;td align="right"&gt;33451&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;32423&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;33294&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;CONSOLE_STRINGS&lt;/td&gt; &lt;td align="right"&gt;29259&lt;/td&gt; &lt;td align="right"&gt;28337&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;29071&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;26683&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;FORMAT_WITH_BOXING&lt;/td&gt; &lt;td align="right"&gt;17143&lt;/td&gt; &lt;td align="right"&gt;17210&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;18100&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;16389&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;FORMAT_NO_BOXING&lt;/td&gt; &lt;td align="right"&gt;15814&lt;/td&gt; &lt;td align="right"&gt;15657&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;15936&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;15222&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;FORMAT_STRINGS&lt;/td&gt; &lt;td align="right"&gt;9178&lt;/td&gt; &lt;td align="right"&gt;8999&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;9077&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;8742&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;CONCAT_WITH_BOXING&lt;/td&gt; &lt;td align="right"&gt;12056&lt;/td&gt; &lt;td align="right"&gt;12563&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;14304&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;11329&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;CONCAT_NO_BOXING&lt;/td&gt; &lt;td align="right"&gt;11949&lt;/td&gt; &lt;td align="right"&gt;12240&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;13145&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;11628&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;CONCAT_STRINGS&lt;/td&gt; &lt;td align="right"&gt;5833&lt;/td&gt; &lt;td align="right"&gt;5936&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;6263&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt; &lt;td align="right"&gt;5713&lt;/td&gt; &lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;So, what do we learn from this? Well, a number of things:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;As ever, microbenchmarks like this are pretty variable. I tried to do this on a &amp;quot;quiet&amp;quot; machine, but as you can see the results varied quite a lot. (Over two seconds between best and worst for a particular configuration at times!)  &lt;li&gt;The difference due to boxing with the original code in the book is basically inside the &amp;quot;noise&amp;quot;  &lt;li&gt;The dominant factor of the statement is writing to the console, even when it&amp;#39;s not actually writing to anything real  &lt;li&gt;The next most important factor is whether we convert to string once or three times  &lt;li&gt;The next most important factor is whether we use String.Format or Concat  &lt;li&gt;The least important factor is boxing&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Now I don&amp;#39;t want anyone to misunderstand me - I agree that boxing is less efficient than not boxing, where there&amp;#39;s a choice. Sometimes (as here, in my view) the &amp;quot;more efficient&amp;quot; code is slightly less readable - and the efficiency benefit is often negligible compared with other factors. Exactly the same thing happened in &lt;a href="http://msmvps.com/blogs/jon_skeet/archive/2008/08/01/book-review-accelerated-c-2008-by-trey-nash.aspx"&gt;Accelerated C# 2008&lt;/a&gt;, where a call to &lt;code&gt;Math.Pow(x, 2)&lt;/code&gt; was the dominant factor in a program again designed to show the efficiency of avoiding boxing.&lt;/p&gt; &lt;p&gt;The performance scare of boxing is akin to that of &lt;a href="http://pobox.com/~skeet/csharp/exceptions2.html"&gt;exceptions&lt;/a&gt;, although I suppose it&amp;#39;s more likely that boxing could cause a real performance concern in an otherwise-well-designed program. It used to be a much more common issue, of course, before generics gave us collections which don&amp;#39;t require boxing/unboxing to add/fetch data.&lt;/p&gt; &lt;p&gt;In short: yes, boxing has a cost. But please look at it in context, and if you&amp;#39;re going to start making claims about how much faster code will run when it avoids boxing, at least provide an example where it actually contributes significantly to the overall execution cost.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1650177" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/CSharpDevCenter/default.aspx">CSharpDevCenter</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/CSharpDev/default.aspx">CSharpDev</category></item><item><title>Book Review: Programming C# 3.0 by Jesse Liberty and Donald Xie</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/09/28/book-review-programming-c-3-0-by-jesse-liberty-and-donald-xie.aspx</link><pubDate>Sun, 28 Sep 2008 00:59:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1649100</guid><dc:creator>skeet</dc:creator><slash:comments>14</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1649100</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1649100</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/09/28/book-review-programming-c-3-0-by-jesse-liberty-and-donald-xie.aspx#comments</comments><description>&lt;h3&gt;Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://oreilly.com/catalog/9780596527433/"&gt;The O&amp;#39;Reilly page&lt;/a&gt; (errata etc)  &lt;/li&gt;
&lt;li&gt;&lt;a href="http://71.248.178.27/LA/MyBooks.html"&gt;Jesse Liberty&amp;#39;s page for his various books&lt;/a&gt;  &lt;/li&gt;
&lt;li&gt;Buy it from &lt;a href="http://www.amazon.com/dp/0596527438"&gt;Amazon&lt;/a&gt; or &lt;a href="http://search.barnesandnoble.com/Programming-C-30/Jesse-Liberty/e/9780596527433/?itm=1"&gt;Barnes and Noble&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Disclaimer&lt;/h3&gt;
&lt;p&gt;One reader commented that a previous book review was too full of &amp;quot;this is only my personal opinion&amp;quot; and other such disclaimers. I think it&amp;#39;s still important to declare the situation, but I can see how it can get annoying if done throughout the review. So instead, I&amp;#39;ve lumped everything together here. Please bear these points in mind while reading the whole review:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Obviously this book competes with C# in Depth, although probably not very much.  &lt;/li&gt;
&lt;li&gt;I was somewhat prejudiced against the book by seeing that the sole 5-star review for it on Amazon was by Jesse Liberty himself. Yes, he wanted to explain why he wrote the book and why he&amp;#39;s proud of it, but giving yourself a review isn&amp;#39;t the right way to go about it.  &lt;/li&gt;
&lt;li&gt;I&amp;#39;ve seen a previous edition of the book (for C# 2.0) and been unimpressed at the coverage of some of the new features.  &lt;/li&gt;
&lt;li&gt;I&amp;#39;m a nut for technical accuracy, particularly when it comes to terminology. More on this later, but if you don&amp;#39;t mind reading (and then presumably using) incorrect terminology, you&amp;#39;re likely to have a lot better time with this book than I did.  &lt;/li&gt;
&lt;li&gt;I suspect I have higher expectations for established, prolific authors such as Jesse Liberty than for newcomers to the world of writing.  &lt;/li&gt;
&lt;li&gt;I&amp;#39;m really not the target market for this book.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay, with all that out of the way, let&amp;#39;s get cracking.&lt;/p&gt;
&lt;h3&gt;Contents and target audience&lt;/h3&gt;
&lt;p&gt;According to the preface, Programming C# 3.0 (PC# from now on) is for people learning C# for the first time, or brushing up on it. There&amp;#39;s an expectation that you probably already know another language - it wouldn&amp;#39;t be impossible to learn C# from the book without any prior development experience, but the preface explicitly acknowledges that it would be reasonably tough. That&amp;#39;s a fair comment - probably fair for &lt;em&gt;any&lt;/em&gt; book, in fact. I have yet to read anything which made me think it would be a wonderful way to teach someone to program from absolute scratch. Likewise the preface recommends C# 3.0 in a Nutshell for a more detailed look at the language, for more expert readers. Again, that&amp;#39;s reasonable - it&amp;#39;s clearly not aiming to go into the same level of depth as Accelerated C# 2008 or C# in Depth.&lt;/p&gt;
&lt;p&gt;The book is split into 4 parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The C# language: pretty much what you&amp;#39;d expect, except that not all of the language coverage is in this part (most of the new features of C# 3.0 are in the second part) and some non-language coverage is included (regular expressions and collections) - about 270 pages  &lt;/li&gt;
&lt;li&gt;C# and Data: LINQ, XML (the DOM API and a bit of LINQ to XML), database access (ADO.NET and LINQ to SQL) - about 100 pages  &lt;/li&gt;
&lt;li&gt;Programming with C#: introductions to ASP.NET, WPF and Windows Forms - about 85 pages  &lt;/li&gt;
&lt;li&gt;The CLR and the .NET Framework: attributes, reflection, threading, I/O and interop - about 110 pages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can tell, the bulk of it is in the language part, which is fine by me and reflects the title accurately. I&amp;#39;ll focus on that part of the book in this review, and the first chapter of part 2, which deals with the LINQ parts of C# 3.0. To be honest, I don&amp;#39;t think the rest of the book actually adds much value, simply because they skim over the surface of their topics &lt;em&gt;so&lt;/em&gt; lightly. Part 3 would make a reasonable series of videos - and indeed that&amp;#39;s how it&amp;#39;s written, basically in the style of &amp;quot;Open Visual Studio, start a new WinForms project, now drag a control over here&amp;quot; etc. I&amp;#39;ve never been fond of that style for a book, although it works well in screencasts.&lt;/p&gt;
&lt;p&gt;The non-LINQ database and XML chapters in part 2 seemed relatively pointless too - I got the feeling that they&amp;#39;d been present in older editions and so had just stayed in by default. With the extra space available from cutting these, a much better job could have been done on LINQ to SQL and LINQ to XML. The latter gets particularly short-changed in PC#, with a mere 4 pages devoted to it! (C# in Depth is much less of a &amp;quot;libraries&amp;quot; book but I still found over 6 pages to devote to it. Not a lot, I&amp;#39;ll grant you.)&lt;/p&gt;
&lt;p&gt;Part 4 has potential, and is more useful than the previous parts - reflection, threading, IO and interop are all important topics (although I&amp;#39;d probably drop interop in favour of internationalization or something similar) - but they&amp;#39;re just not handled terribly well. The threading chapter talks about using lock &lt;em&gt;or&lt;/em&gt; Monitor, but never states that &lt;code&gt;lock&lt;/code&gt; is just shorthand for &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;finally&lt;/code&gt; blocks which use &lt;code&gt;Monitor&lt;/code&gt;; no mention is made of the memory model or volatility; aborting threads is demonstrated but not warned about; the examples always lock on &lt;code&gt;this&lt;/code&gt; without explaining that it&amp;#39;s generally thought to be a bad idea. The IO chapter uses &lt;code&gt;TextReader&lt;/code&gt; (usually via &lt;code&gt;StreamReader&lt;/code&gt;) but never mentions the &lt;em&gt;crucial&lt;/em&gt; topic of character encodings (it uses &lt;code&gt;Encoding.ASCII&lt;/code&gt; but without really explaining it) - and most damning of all, as far as I can tell there&amp;#39;s not a &lt;em&gt;single&lt;/em&gt; &lt;code&gt;using&lt;/code&gt; statement in the entire chapter. There are calls to &lt;code&gt;Close()&lt;/code&gt; at the end of each example, and there&amp;#39;s a very &lt;em&gt;brief&lt;/em&gt; mention saying that you should always explicitly close streams - but without saying that you should use a &lt;code&gt;using&lt;/code&gt; statement or &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;finally&lt;/code&gt; for this purpose.&lt;/p&gt;
&lt;p&gt;Okay, enough on those non-language topics - let&amp;#39;s look at the bulk of the book, which is about the language.&lt;/p&gt;
&lt;h3&gt;Language coverage&lt;/h3&gt;
&lt;p&gt;PC# starts from scratch, so it&amp;#39;s got the whole language to cover in about 300 pages. It would be unreasonable to expect it to provide as much attention to detail as C# in Depth, which (for the most part) only looks at the new features of C# 2.0 and 3.0. (On the other hand, if the remaining 260 pages had been given to the language as well, a lot more ground could have been covered.) It&amp;#39;s also worth bearing in mind that the book is &lt;em&gt;not&lt;/em&gt; aimed at confident/competent C# developers - it&amp;#39;s written for newcomers, and delving into tricky issues like generic variance would be plain mean. However, I&amp;#39;m still not impressed with what&amp;#39;s been left out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There&amp;#39;s &lt;em&gt;no mention&lt;/em&gt; of nullable types as far as I can tell - indeed, the list of operators omit the null-coalescing operator (??).  &lt;/li&gt;
&lt;li&gt;Generics are really only talked about in the context of collections - despite the fact that to understand any LINQ documentation, you really will need to understand generic delegates. Generic constraints are only likewise only mentioned in the context of collections, and only what I call a &amp;quot;derivation type constraint&amp;quot; (e.g. &lt;code&gt;T : IComparable&amp;lt;T&amp;gt;&lt;/code&gt;) (as far as I can tell the spec doesn&amp;#39;t give this a name). There&amp;#39;s no coverage of &lt;code&gt;default(T)&lt;/code&gt; - although the &amp;quot;default value of a type&amp;quot; is mentioned elsewhere, with an incorrect explanation.  &lt;/li&gt;
&lt;li&gt;Collection initializers aren&amp;#39;t explained as far as I can tell, although I seem to recall seeing one in an example. They&amp;#39;re not mentioned in the index.  &lt;/li&gt;
&lt;li&gt;Iterator blocks (and the &lt;code&gt;yield&lt;/code&gt; contextual keyword) are likewise absent from the index, although there&amp;#39;s definitely one example of &lt;code&gt;yield return&lt;/code&gt; when &lt;code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/code&gt; is covered. The coverage given is minimal, with no mention of the completely different way that this executes compared with normal methods.  &lt;/li&gt;
&lt;li&gt;Query expression coverage is limited: although &lt;code&gt;from&lt;/code&gt;, &lt;code&gt;where&lt;/code&gt;, &lt;code&gt;select&lt;/code&gt;, &lt;code&gt;orderby&lt;/code&gt;, &lt;code&gt;join&lt;/code&gt; and &lt;code&gt;group&lt;/code&gt; are covered, there&amp;#39;s no mention of &lt;code&gt;let&lt;/code&gt;, the difference between &lt;code&gt;join&lt;/code&gt; and &lt;code&gt;join ... into&lt;/code&gt;, explicitly typed range variables, or query continuations. The translation process isn&amp;#39;t really explained clearly, and the text pretty much states that it will always use extension methods.  &lt;/li&gt;
&lt;li&gt;Expression trees aren&amp;#39;t referenced to my knowledge; there&amp;#39;s one piece of text which attempts to mention them but just calls them &amp;quot;expressions&amp;quot; - which are of course entirely different. We&amp;#39;ll come onto terminology in a minute.  &lt;/li&gt;
&lt;li&gt;Only the simplest (and admittedly most common by a &lt;i&gt;huge&lt;/i&gt; margin) form of &lt;code&gt;using&lt;/code&gt; directives is shown - no extern aliases, no namespace aliases, not even &lt;code&gt;using Foo = System.Console;&lt;/code&gt;  &lt;/li&gt;
&lt;li&gt;Partial methods aren&amp;#39;t mentioned.  &lt;/li&gt;
&lt;li&gt;Implicitly typed arrays aren&amp;#39;t covered.  &lt;/li&gt;
&lt;li&gt;Static classes may be mentioned in passing (not sure) but not really explained.  &lt;/li&gt;
&lt;li&gt;Object initializers are shown in one form only, ditto anonymous object initializer expressions  &lt;/li&gt;
&lt;li&gt;Only field-like events are shown. The authors spend several pages on an example of bad code which just has a public delegate variable, and then try to blame delegates for the problem (which is really having a public variable). The solution is (of course) to use an event, but there&amp;#39;s little to no explanation of the nature of events as pairs of methods, a bit like properties but with subscribe/unsubscribe behaviour instead of data fetch/mutate.  &lt;/li&gt;
&lt;li&gt;Anonymous methods and lambda expressions are covered, but with &lt;em&gt;very&lt;/em&gt; little text about the closure aspect of them. This is about it: &amp;quot;[...] and the anonymous method has access to the variables in the scope in which they are defined:&amp;quot; (followed by an example which doesn&amp;#39;t demonstrate the use of such variables at all).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I suspect there&amp;#39;s more, but you get the general gist. I&amp;#39;m not saying that all of these should have been covered and in great detail, but really - no mention of nullable types &lt;em&gt;at all&lt;/em&gt;? Is it really more appropriate &lt;em&gt;in a supposed language book&lt;/em&gt; to spend several pages building an asynchronous file server than to actually list all the operators accurately?&lt;/p&gt;
&lt;p&gt;Okay, I&amp;#39;m clearly beginning to rant by now. The limited coverage is annoying, but it&amp;#39;s not &lt;em&gt;that&lt;/em&gt; bad. Yes, I think the poor/missing coverage of generics and nullable types is a real problem, but it&amp;#39;s not enough to get me really cross. It&amp;#39;s the massive abuse of terminology which winds me up.&lt;/p&gt;
&lt;h3&gt;Accuracy&lt;/h3&gt;
&lt;p&gt;I&amp;#39;ll say this for PC# - if you ignore the terminology abuse, it&amp;#39;s &lt;em&gt;mostly&lt;/em&gt; accurate. There are definitely &amp;quot;saying something incorrect&amp;quot; issues (e.g. an implication that ref/out can only be used with value type parameters; the statement that reference types in an array aren&amp;#39;t initialized to their default value (they are - the default value is null); the claim that extension methods can only access public members of target types (they have the same access as normal - so if the extension method is in the same assembly as the target type, for instance, it could access internal members)) but the biggest problem is that of terminology - along with sloppy code, including its formatting.&lt;/p&gt;
&lt;p&gt;The authors confuse objects, values, variables, expressions, parameters, arguments and all kinds of other things. These have well-defined meanings, and they&amp;#39;re there for a reason. They do have footnotes explaining that they&amp;#39;re &lt;em&gt;deliberately&lt;/em&gt; using the wrong terminology - but that doesn&amp;#39;t make it any better. Here are the three footnotes, and my responses to them:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The terms &lt;em&gt;argument&lt;/em&gt; and &lt;em&gt;parameter&lt;/em&gt; are often used interchangably, though some programmers insist on differentiating between the parameter declaration and the arguments passed in when the method is invoked.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Just because others abuse terms doesn&amp;#39;t mean it&amp;#39;s right for a book to do so. It&amp;#39;s not that &lt;em&gt;programmers&lt;/em&gt; insist on differentiating between the two - the &lt;em&gt;specification&lt;/em&gt; does. Now, to lighten things up a bit I&amp;#39;ll acknowledge that this one isn&amp;#39;t always easy to deal with. There are plenty of times where I&amp;#39;ve tried really hard to use the right term and just not ended up with a satisfactory bit of wording. However, at least I&amp;#39;ve tried - and where it&amp;#39;s easy, I&amp;#39;ve done the right thing. I wish the authors had the same attitude. (They do the same with the conditional operator, calling it &amp;quot;the ternary operator&amp;quot;. It&amp;#39;s &lt;em&gt;a&lt;/em&gt; ternary operator. Having three operands is part of its nature - it&amp;#39;s not a description of its behaviour. Again, lots of other people get this wrong. Perhaps if all &lt;em&gt;books&lt;/em&gt; got it right, more developers would too.) Next up:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Throughout this book, I use the term &lt;em&gt;object&lt;/em&gt; to refer to reference and value types. There is some debate in the fact that Microsoft has implemented the value types as though they inherited from the root class Object (and thus, you may call all of Object&amp;#39;s methods on any value type, including the built-in types such as int.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To me, this pretty much reads as &amp;quot;I&amp;#39;m being sloppy, but I&amp;#39;ve got half an excuse.&amp;quot; It&amp;#39;s true that the C# specification isn&amp;#39;t clear on this point - although the CLI spec is crystal clear. Personally, it just feels &lt;em&gt;wrong&lt;/em&gt; to talk about the value 5 as an object. It&amp;#39;s an object when it&amp;#39;s boxed, of course (and if you call any &lt;code&gt;Object&lt;/code&gt; methods on a value type which haven&amp;#39;t been overridden by that type, it gets boxed at that point) but otherwise I really don&amp;#39;t think of it as an object. An &lt;em&gt;instance&lt;/em&gt; of the type, yes - but not an object. So yes, I&amp;#39;ll acknowledge that there&amp;#39;s a little wiggle room here - but I believe it&amp;#39;s going to confuse readers more than it helps them.&lt;/p&gt;
&lt;p&gt;It&amp;#39;s the &amp;quot;confusing readers more than it helps them&amp;quot; part which is important. I&amp;#39;m not above a little bit of shortcutting myself - in C# in Depth, I refer to automatically implemented properties as &amp;quot;automatic properties&amp;quot; (after explicitly saying what I&amp;#39;m doing) and I refer to the versions of C# as 1, 2 and 3 instead of 1.0, 1.2, 2.0 and 3.0. In both these cases, I believe it adds to the readability of the book without giving any room for confusion. That&amp;#39;s very different from what&amp;#39;s going on in PC#, in my view. I&amp;#39;ve saved the most galling example of this for last:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As noted earlier, &lt;code&gt;btnUpdate&lt;/code&gt; and &lt;code&gt;btnDelete&lt;/code&gt; are actually variables that refer to the unnamed instances on the heap. For simplicity, we&amp;#39;ll refer to these as the names of the objects, keeping in mind that this is just short-hand for &amp;quot;the name of the variables that refer to the unnamed instances on the heap.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This one&amp;#39;s the killer. It sounds &lt;em&gt;relatively&lt;/em&gt; innocuous until you see the results. Things like this (from P63):&lt;/p&gt;
&lt;div class="code"&gt;ListBox myListBox;&amp;nbsp; &lt;span class="InlineComment"&gt;// instantiate a ListBox object&lt;/span&gt; &lt;/div&gt;
&lt;p&gt;No, that code doesn&amp;#39;t instantiate anything. It &lt;em&gt;declares&lt;/em&gt; a &lt;em&gt;variable &lt;/em&gt;- and that&amp;#39;s all. The comment isn&amp;#39;t non-sensical - the idea of some code which &lt;em&gt;does&lt;/em&gt; instantiate a &lt;code&gt;ListBox&lt;/code&gt; object clearly makes sense - but it&amp;#39;s not what&amp;#39;s happening in &lt;em&gt;this&lt;/em&gt; code (in C# - it &lt;em&gt;would&lt;/em&gt; in C++, which makes it even more confusing). That&amp;#39;s just one example - the same awful sloppiness (which implies something &lt;em&gt;completely incorrect&lt;/em&gt;) permeates the whole book. Time and time again we&amp;#39;re told about instances being created when they&amp;#39;re not. From P261:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Clock class must then create an instance of this delegate, which it does on the following line:&lt;/p&gt;
&lt;div class="code"&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt; SecondChangeHandler SecondChanged; &lt;/div&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why do I care about this so much? Because I see the results of it on the newsgroups, constantly. How can I blame developers for failing to communicate properly about the problems they&amp;#39;re having if their source of learning is so sloppy and inaccurate? How can they get an accurate mental model of the language if they&amp;#39;re being told that objects are being instantiated when they&amp;#39;re not? Communication and a clear mental model are &lt;em&gt;very&lt;/em&gt; important to me. They&amp;#39;re why I get riled up when people perpetuate myths about where structs &amp;quot;live&amp;quot; or how parameters are passed. PC# had me clenching my fists on a regular basis.&lt;/p&gt;
&lt;p&gt;These are examples where the authors apparently &lt;em&gt;knew&lt;/em&gt; they were abusing the terminology. There are other examples where I believe it&amp;#39;s a genuine mistake - calling anonymous methods &amp;quot;anonymous delegates&amp;quot; or &amp;quot;statements that evaluate to a value are called expressions&amp;quot; (statements are &lt;em&gt;made up of&lt;/em&gt; expressions, and expressions don&amp;#39;t have to return a value). I can certainly sympathise with this. Quite where they got the idea that HTML was derived from &amp;quot;Structured Query Markup Language&amp;quot; I don&amp;#39;t know - the word &amp;quot;Query&amp;quot;should have been a red flag - but these things happen.&lt;/p&gt;
&lt;p&gt;In other places the authors are just being sloppy without either declaring that they&amp;#39;re going to be, or just appearing to make typos. In particular, they&amp;#39;re bad at distinguishing between language, framework and runtime. For instance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;quot;C# combines the power and complexity of regular expression syntax [...]&amp;quot; - no, C# itself neither knows nor cares about regular expressions. They&amp;#39;re in the framework.  &lt;/li&gt;
&lt;li&gt;(When talking about iterator blocks) &amp;quot;All the bookkeeping for keeping track of which element is next, resetting the iterator, and so forth is provided for you by the Framework.&amp;quot; - No, this time it &lt;em&gt;is&lt;/em&gt; the C# compiler which is doing all the work. (It doesn&amp;#39;t support reset though.)  &lt;/li&gt;
&lt;li&gt;&amp;quot;Strings can also be created using &lt;em&gt;verbatim&lt;/em&gt; string literals, which start the at (@) symbol. This tells the String constructor that the string should be used verbatim [...]&amp;quot; - No, the String constructor doesn&amp;#39;t know about verbatim string literals. They&amp;#39;re handled by the C# compiler.  &lt;/li&gt;
&lt;li&gt;&amp;quot;The .NET CLR provides isolated storage to allow the application developer to store data on a &lt;em&gt;per-user&lt;/em&gt; basis.&amp;quot; I very much doubt that the CLR code has any idea about this. I expect it to be in the framework libraries.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, if books don&amp;#39;t get this right, how do we expect developers to distinguish between the three? Admittedly sometimes it can be tricky to decide where responsibility lies - but there are plenty of clearcut cases where PC# is just wrong. I doubt that the authors really don&amp;#39;t know the difference - they just don&amp;#39;t seem to think it&amp;#39;s important to get it right.&lt;/p&gt;
&lt;h3&gt;Code&lt;/h3&gt;
&lt;p&gt;I&amp;#39;m mostly going to point out the shortcomings of the code, but on the plus side I believe almost all of it will basically work. There&amp;#39;s one point at which the authors have both a method and a variable with the same name (which is already in the unconfirmed errata) and a few other niggles, but they&amp;#39;re relatively rare. However:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The code frequently ignores naming conventions. Method and class names sometimes start with lower case, and there&amp;#39;s frequent use of horrible names beginning with &amp;quot;my&amp;quot; or &amp;quot;the&amp;quot;.  &lt;/li&gt;
&lt;li&gt;The authors often present several pages of code together, and then take them apart section by section. This isn&amp;#39;t the only book to do this by a long chalk, but I wonder - does anyone really benefit from having the whole thing in a big chunk? Isn&amp;#39;t it better to present small, self-contained examples?  &lt;/li&gt;
&lt;li&gt;As mentioned before, the uses of &lt;code&gt;using&lt;/code&gt; statements are few and far between.  &lt;/li&gt;
&lt;li&gt;The whitespace is all over the place. The indentation level changes all the time, and sometimes there are outdents in the middle of blocks. Occasionally newlines have actually been missed out, and in other cases (particularly at the start of class bodies) there are two blank lines for no reason at all. (The latter is very odd in a book, where vertical whitespace is seen as extremely valuable.) Sometimes there&amp;#39;s excessive (to my mind) spacing Just as an example (which is explicitly labelled as non-compiling code, so I&amp;#39;m not faulting it at all for that):
&lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Console;&lt;br /&gt;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Hello&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WriteLine(&lt;span class="String"&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt;
I promise you that&amp;#39;s &lt;i&gt;exactly&lt;/i&gt; how it appears in the book. Now this may have started out as a fault of the type-setter, but the authors should have picked it up before publication, IMO. I could understand there being a &lt;i&gt;few&lt;/i&gt; issues like this (proof-reading code really is hard) but not nearly as many as there are.  &lt;/li&gt;
&lt;li&gt;There are examples of mutable structs (or rather, there&amp;#39;s at least one example), and &lt;em&gt;no warning at all&lt;/em&gt; that mutable value types are a really, really bad idea.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, I don&amp;#39;t want to give the impression I&amp;#39;m an absolute perfectionist when it comes to code in book. For the sake of keeping things simple, sometimes authors don&amp;#39;t seal types where they should, or make them immutable etc. I&amp;#39;m not really looking for production-ready code, and indeed I made this very point in &lt;a href="http://csharpindepth.com/ViewNote.aspx?NoteID=2"&gt;one of the notes&lt;/a&gt; for C# in Depth. However, I draw the line at &lt;code&gt;using&lt;/code&gt; statements, which are important and easy to get right without distracting the reader. Likewise giving variables good names - &lt;code&gt;counter&lt;/code&gt; rather than &lt;code&gt;ctr&lt;/code&gt;, and avoiding those &lt;code&gt;the&lt;/code&gt; and &lt;code&gt;my&lt;/code&gt; prefixes - makes a competent reader more comfortable and can transfer good habits to the novice via osmosis.&lt;/p&gt;
&lt;h3&gt;Writing style and content ordering&lt;/h3&gt;
&lt;p&gt;Time for some good news - when you look beyond the terminology, this is a really easy book to read. I don&amp;#39;t mean that everything in it is simplistic, but the style rarely gets in the way. It&amp;#39;s not dry, and some of the real-world analogies are very good. This may well be Jesse Liberty&amp;#39;s experience as a long-standing author making itself apparent.&lt;/p&gt;
&lt;p&gt;In common with many O&amp;#39;Reilly books, there are two icons which usually signify something worth paying special attention to: a set of paw prints indicating a hint or tip, and a mantrap indicating a commonly encountered issue to be aware of. Given the rest of the review, I suspect you&amp;#39;d be surprised if I agreed with all of the points made in these extra notes - and indeed there are some issues - but most of them are good.&lt;/p&gt;
&lt;p&gt;Likewise there are also notes for the sake of existing Java and C++ developers, which make sense and are useful.&lt;/p&gt;
&lt;p&gt;I don&amp;#39;t agree with some of the choices made in terms of how and when to present some concepts. I found the way of explaining query expressions confusing, as it interleaved &amp;quot;here&amp;#39;s a new part of query expressions&amp;quot; with &amp;quot;here&amp;#39;s a new feature (e.g. anonymous types, extension methods).&amp;quot; It will come as no surprise to anyone who&amp;#39;s read C# in Depth that I prefer the approach of presenting all the building blocks first, and then showing how query expressions use all those features. There&amp;#39;s a note explaining why the authors have done what they&amp;#39;ve done, but I don&amp;#39;t buy it. One important thing with the &amp;quot;building blocks first&amp;quot; approach is to present a preliminary example or two, to give an idea of where we&amp;#39;re headed. I&amp;#39;ve forgotten to do that in the past (in a talk) and regretted it - but I don&amp;#39;t regret the overall way of tackling the topic.&lt;/p&gt;
&lt;p&gt;On a &lt;em&gt;slightly&lt;/em&gt; different note, I would have presented some of the earlier topics in a different order too. For instance, I regard structs and interfaces as more commonly used and fundamental topics than operator overloading. (While C# developers tend not to create their own structs often, they &lt;em&gt;use&lt;/em&gt; them all the time. When was the last time you wrote a program without an int in it?) This is a minor nit - and one which readers may remember I also mentioned for Accelerated C# 2008.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s one final point I&amp;#39;d like to make, but which doesn&amp;#39;t really fit anywhere else - it&amp;#39;s about Jesse Liberty&amp;#39;s dedication. Most people dedicate books to friends, colleages etc. Here&amp;#39;s Jesse&amp;#39;s:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This book is dedicated to those who come out, loud, and in your face and in the most inappropriate places. We will look back at this time and shake our heads in wonder. In 49 states, same-sex couples are denied the right to marry, though incarcerated felons are not. In 36 states, you can legally be denied housing just for being q-u-e-e-r. In more than half the states, there is no law protecting LGBT children from harassment in school, and the suicide rate among q-u-e-e-r teens is 400 percent higher than among straight kids. And, we are still kicking gay heroes out of the military despite the fact that the Israelis and our own NSA, CIA, and FBI are all successfully integrated. So yes, this dedication is to those of us who are out, full-time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(I&amp;#39;ve had to spell out q-u-e-e-r as otherwise the blog software replaces it with asterisks. Grr.) I&amp;#39;m straight, but I support Jesse&amp;#39;s sentiment 100%. I can&amp;#39;t remember when I first started taking proper notice of the homophobia in the world, but it was probably at university. This dedication does nothing to help or hinder the reader with C#, but to my mind it still makes it a better book.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;In short, I&amp;#39;m afraid I wouldn&amp;#39;t recommend Programming C# 3.0 to potential readers. There are much better books out there: ones which won&amp;#39;t make it harder for the reader to talk about their code with others, in particular. It&amp;#39;s not all bad by any means, but the mixture of sloppy use of terminology and poor printed code is enough of a problem to make me give a general thumbs down.&lt;/p&gt;
&lt;p&gt;Next up will be CLR via C#, by Jeffrey Richter.&lt;/p&gt;
&lt;h3&gt;Response from Jesse Liberty&lt;/h3&gt;
&lt;p&gt;As normal, I mailed the author (in this case just Jesse Liberty - I confess I didn&amp;#39;t look for Donald Xie&amp;#39;s email address) and very promptly received a nice response. He asked me to add the following as his reaction:&lt;/p&gt;
&lt;div class="reaction"&gt;I believe the book is very good for most real-world programmers and the publisher and I are dedicated to making the next revision a far better book, by correcting some of the problems you point out, and by beefing up the coverage of the newer features of the language. &lt;/div&gt;
&lt;p&gt;Also as normal, I&amp;#39;ll be emailing Jesse with a list of the errors I found, so hopefully they can be corrected for the next edition.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1649100" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Book+reviews/default.aspx">Book reviews</category></item><item><title>Logging enumeration flow</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/09/09/logging-enumeration-flow.aspx</link><pubDate>Tue, 09 Sep 2008 07:18:45 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1647209</guid><dc:creator>skeet</dc:creator><slash:comments>12</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1647209</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1647209</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/09/09/logging-enumeration-flow.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;m currently reading &lt;a href="http://www.amazon.com/dp/1590597893"&gt;Pro LINQ: Language Integrated Query in C# 2008&lt;/a&gt; by Joe Rattz and yesterday I came across a claim about &lt;code&gt;Enumerable.Intersect&lt;/code&gt; which didn&amp;#39;t quite ring true. I consulted MSDN and the documentation is exactly the same as the book. Here&amp;#39;s what it says:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;When the object returned by this method is enumerated, Intersect enumerates &lt;i&gt;first&lt;/i&gt;, collecting all distinct elements of that sequence. It then enumerates &lt;i&gt;second&lt;/i&gt;, marking those elements that occur in both sequences. Finally, the marked elements are yielded in the order in which they were collected. &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;(&lt;i&gt;first&lt;/i&gt; is the first parameter, the one which the method appears to be called on when using it as an extension method. &lt;em&gt;second&lt;/em&gt; is the second parameter - the other sequence involved.)&lt;/p&gt; &lt;p&gt;This seems to be needlessly restrictive. In particular, it doesn&amp;#39;t allow you to work with an infinite sequence on either side. It also means loading the whole of both sequences into memory at the same time. Given the way that &lt;code&gt;Join&lt;/code&gt; works, I was surprised to see this. So I thought I&amp;#39;d test it. This raised the question of how you trace the flow of a sequence - how do you know when data is being pulled from it? The obvious answer is to create a new sequence which fetches from the old one, logging as it goes. Fortunately this is really easy to implement: &lt;/p&gt; &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Extensions&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; WithLogging&amp;lt;T&amp;gt;(&lt;span class="Keyword"&gt;this&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; source, &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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 class="ReferenceType"&gt;string&lt;/span&gt; name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;foreach&lt;/span&gt; (T element &lt;span class="Statement"&gt;in&lt;/span&gt; source)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;{0}: {1}&amp;quot;&lt;/span&gt;, name, element);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; element;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt; &lt;p&gt;We keep a name for the sequence so we can easily trace which sequence is being pulled from at what point. Now let&amp;#39;s apply this logging to a call to &lt;code&gt;Intersect&lt;/code&gt;: &lt;/p&gt; &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;br /&gt;&lt;span class="InlineComment"&gt;// Compile alongside the Extensions class&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Test&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; first = Enumerable.Range(1, 5).WithLogging(&lt;span class="String"&gt;&amp;quot;first&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; second = Enumerable.Range(3, 5).WithLogging(&lt;span class="String"&gt;&amp;quot;second&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;foreach&lt;/span&gt; (&lt;span class="ValueType"&gt;int&lt;/span&gt; i &lt;span class="Statement"&gt;in&lt;/span&gt; first.Intersect(second))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Intersect: {0}&amp;quot;&lt;/span&gt;, i);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt; &lt;p&gt;As you can see, we&amp;#39;re intersecting the numbers 1-5 with the numbers 3-7 - the intersection should clearly be 3-5. We&amp;#39;ll see a line of output each time data is pulled from either &lt;code&gt;first&lt;/code&gt; or &lt;code&gt;second&lt;/code&gt;, and also when the result of &lt;code&gt;Intersect&lt;/code&gt; yields a value. Given the documentation and the book, one would expect to see this output: &lt;/p&gt; &lt;div class="output"&gt;&lt;span class="Attention"&gt;// Theoretical output. It doesn&amp;#39;t really do this&lt;/span&gt;&lt;br /&gt;first: 1&lt;br /&gt;first: 2&lt;br /&gt;first: 3&lt;br /&gt;first: 4&lt;br /&gt;first: 5&lt;br /&gt;second: 3&lt;br /&gt;second: 4&lt;br /&gt;second: 5&lt;br /&gt;second: 6&lt;br /&gt;second: 7&lt;br /&gt;Intersect: 3&lt;br /&gt;Intersect: 4&lt;br /&gt;Intersect: 5&lt;/div&gt; &lt;p&gt;Fortunately, it &lt;i&gt;actually&lt;/i&gt; works exactly how I&amp;#39;d expect: the second sequence is evaluated fully, then the first is evaluated in a streaming fashion, with results being yielded as they&amp;#39;re found. (This means that, if you&amp;#39;re sufficiently careful with the result, e.g. by calling &lt;code&gt;Take&lt;/code&gt; with a suitably small value, the first sequence can be infinite.) Here&amp;#39;s the actual output demonstrating that:  &lt;div class="output"&gt;&lt;span class="Attention"&gt;// Actual output.&lt;/span&gt;&lt;br /&gt;second: 3&lt;br /&gt;second: 4&lt;br /&gt;second: 5&lt;br /&gt;second: 6&lt;br /&gt;second: 7&lt;br /&gt;first: 1&lt;br /&gt;first: 2&lt;br /&gt;first: 3&lt;br /&gt;Intersect: 3&lt;br /&gt;first: 4&lt;br /&gt;Intersect: 4&lt;br /&gt;first: 5&lt;br /&gt;Intersect: 5&lt;/div&gt; &lt;h3&gt;Initial Conclusion&lt;/h3&gt; &lt;p&gt;There are two interesting points here, to my mind. The first is demonstrating that the documentation for &lt;code&gt;Intersect&lt;/code&gt; is wrong - the real code is more sensible than the docs. That&amp;#39;s not as important as seeing how easy it is to log the flow of sequence data - as simple as adding a single extension method and calling it. (You could do it with a &lt;code&gt;Select&lt;/code&gt; projection which writes the data and then yields the value of course, but I think this is neater.) &lt;/p&gt; &lt;p&gt;I&amp;#39;m hoping to finish reading Joe&amp;#39;s book this week, and write the review over the weekend, by the way.&lt;/p&gt; &lt;h3&gt;Update (Sept. 11th 2008)&lt;/h3&gt; &lt;p&gt;Frederik Siekmann replied to this post with a thrilling alternative implementation to stream the intersection, which takes alternating elements from the two sequences involved. It&amp;#39;s a bit more memory hungry (with three sets of elements to remember instead of just one) but it means that we can deal with two infinite streams, if we&amp;#39;re careful. Here&amp;#39;s a complete example:&lt;/p&gt; &lt;div class="code"&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br /&gt;&lt;span class="Namespace"&gt;using&lt;/span&gt; System.Linq;&lt;br /&gt;&lt;br /&gt;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Extensions&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; AlternateIntersect&amp;lt;T&amp;gt;(&lt;span class="Keyword"&gt;this&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; first, IEnumerable&amp;lt;T&amp;gt; second)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; intersection = &lt;span class="Keyword"&gt;new&lt;/span&gt; HashSet&amp;lt;T&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; firstSet = &lt;span class="Keyword"&gt;new&lt;/span&gt; HashSet&amp;lt;T&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; secondSet = &lt;span class="Keyword"&gt;new&lt;/span&gt; HashSet&amp;lt;T&amp;gt;();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Namespace"&gt;using&lt;/span&gt; (IEnumerator&amp;lt;T&amp;gt; firstEnumerator = first.GetEnumerator())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Namespace"&gt;using&lt;/span&gt; (IEnumerator&amp;lt;T&amp;gt; secondEnumerator = second.GetEnumerator())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ValueType"&gt;bool&lt;/span&gt; firstHasValues = firstEnumerator.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="ValueType"&gt;bool&lt;/span&gt; secondHasValues = secondEnumerator.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;while&lt;/span&gt; (firstHasValues &amp;amp;&amp;amp; secondHasValues)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T currentFirst = firstEnumerator.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T currentSecond = secondEnumerator.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (!intersection.Contains(currentFirst) &amp;amp;&amp;amp; &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; secondSet.Contains(currentFirst))&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intersection.Add(currentFirst);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; currentFirst;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; firstSet.Add(currentFirst);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (!intersection.Contains(currentSecond) &amp;amp;&amp;amp; &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; firstSet.Contains(currentSecond))&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intersection.Add(currentSecond);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; currentSecond;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; secondSet.Add(currentSecond);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; firstHasValues = firstEnumerator.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; secondHasValues = secondEnumerator.MoveNext();&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (firstHasValues)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;do&lt;/span&gt;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T currentFirst = firstEnumerator.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (!intersection.Contains(currentFirst) &amp;amp;&amp;amp; &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; secondSet.Contains(currentFirst))&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intersection.Add(currentFirst);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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 class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; currentFirst;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;span class="Statement"&gt;while&lt;/span&gt; (firstEnumerator.MoveNext());&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (secondHasValues)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;do&lt;/span&gt;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T currentSecond = secondEnumerator.Current;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;if&lt;/span&gt; (!intersection.Contains(currentSecond) &amp;amp;&amp;amp; &lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; firstSet.Contains(currentSecond))&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; intersection.Add(currentSecond);&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&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 class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; currentSecond;&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;span class="Statement"&gt;while&lt;/span&gt; (secondEnumerator.MoveNext());&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; WithLogging&amp;lt;T&amp;gt;(&lt;span class="Keyword"&gt;this&lt;/span&gt; IEnumerable&amp;lt;T&amp;gt; source, &lt;span class="ReferenceType"&gt;string&lt;/span&gt; name)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;foreach&lt;/span&gt; (T element &lt;span class="Statement"&gt;in&lt;/span&gt; source)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(&lt;span class="ReferenceType"&gt;string&lt;/span&gt;.Format(&lt;span class="String"&gt;&amp;quot;{0}: {1}&amp;quot;&lt;/span&gt;, name, element));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;yield&lt;/span&gt;&amp;nbsp;&lt;span class="Statement"&gt;return&lt;/span&gt; element;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="ReferenceType"&gt;class&lt;/span&gt; Test&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt; Main()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; positiveIntegers = Enumerable.Range(0, &lt;span class="ValueType"&gt;int&lt;/span&gt;.MaxValue);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; multiplesOfTwo = positiveIntegers.Where(x =&amp;gt; (x%2) == 0)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .WithLogging(&lt;span class="String"&gt;&amp;quot;Twos&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Linq"&gt;var&lt;/span&gt; multiplesOfThree = positiveIntegers.Where(x =&amp;gt; (x%3) == 0)&lt;br /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .WithLogging(&lt;span class="String"&gt;&amp;quot;Threes&amp;quot;&lt;/span&gt;);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="Statement"&gt;foreach&lt;/span&gt; (&lt;span class="ValueType"&gt;int&lt;/span&gt; x &lt;span class="Statement"&gt;in&lt;/span&gt; multiplesOfTwo.AlternateIntersect(multiplesOfThree).Take(10))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine (&lt;span class="String"&gt;&amp;quot;AlternateIntersect: {0}&amp;quot;&lt;/span&gt;, x);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/div&gt; &lt;p&gt;Most of the code is the alternating intersection - the test at the end just shows intersection of the sequence 2, 4, 6, 8... with 3, 6, 9, 12... The output shows elements being taken from both sequences, and yielded when a match is found. It&amp;#39;s important that we limit the output in some way - in the above code we call &lt;code&gt;Take(10)&lt;/code&gt; but anything which prevents the loop from just executing until we run out of memory is fine.&lt;/p&gt; &lt;div class="output"&gt;Twos: 0&lt;br /&gt;Threes: 0&lt;br /&gt;AlternateIntersect: 0&lt;br /&gt;Twos: 2&lt;br /&gt;Threes: 3&lt;br /&gt;Twos: 4&lt;br /&gt;Threes: 6&lt;br /&gt;Twos: 6&lt;br /&gt;Threes: 9&lt;br /&gt;AlternateIntersect: 6&lt;br /&gt;Twos: 8&lt;br /&gt;Threes: 12&lt;br /&gt;Twos: 10&lt;br /&gt;Threes: 15&lt;br /&gt;Twos: 12&lt;br /&gt;Threes: 18&lt;br /&gt;AlternateIntersect: 12&lt;br /&gt;Twos: 14&lt;br /&gt;Threes: 21&lt;br /&gt;Twos: 16&lt;br /&gt;Threes: 24&lt;br /&gt;Twos: 18&lt;br /&gt;Threes: 27&lt;br /&gt;AlternateIntersect: 18&lt;br /&gt;(etc)&lt;/div&gt; &lt;p&gt;That&amp;#39;s really neat. Quite how often it&amp;#39;ll be useful is a different matter, but I find this kind of thing fascinating to consider. Thanks Frederik!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1647209" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/LINQ/default.aspx">LINQ</category></item><item><title>Data Structures and Algorithms: new free eBook available (first draft)</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/08/29/data-structures-and-algorithms-new-free-ebook-available-first-draft.aspx</link><pubDate>Fri, 29 Aug 2008 19:25:17 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1646210</guid><dc:creator>skeet</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1646210</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1646210</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/08/29/data-structures-and-algorithms-new-free-ebook-available-first-draft.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve been looking at this for a while: &lt;a title="http://dotnetslackers.com/projects/Data-Structures-And-Algorithms/" href="http://dotnetslackers.com/projects/Data-Structures-And-Algorithms/"&gt;Data Structures and Algorithms: Annotated reference with examples&lt;/a&gt;. It&amp;#39;s only in &amp;quot;first draft&amp;quot; stage at the moment, but the authors would love your feedback (as would I). Somehow I&amp;#39;ve managed to end up as the editor and proof-reader, although due to my holiday the version currently available doesn&amp;#39;t have many of my edits in. It&amp;#39;s a non-academic data structures and algorithms book, intended (as I see it, anyway) as a good starting point for those who know that they ought to be more aware of the data structures they use every day (lists, heaps etc) but don&amp;#39;t have an academic background in computer science.&lt;/p&gt; &lt;p&gt;An implementation will be available in both Java and C#, I believe.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1646210" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Java/default.aspx">Java</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Book review: Accelerated C# 2008 by Trey Nash</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/08/01/book-review-accelerated-c-2008-by-trey-nash.aspx</link><pubDate>Fri, 01 Aug 2008 22:05:41 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1643045</guid><dc:creator>skeet</dc:creator><slash:comments>21</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1643045</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1643045</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/08/01/book-review-accelerated-c-2008-by-trey-nash.aspx#comments</comments><description>&lt;p&gt;Time for another book review, and this time it&amp;#39;s a due to a recommendation from a reader who has this one, C# in Depth &lt;em&gt;and&lt;/em&gt; Head First C#.&lt;/p&gt; &lt;h3&gt;Resources&lt;/h3&gt; &lt;ul&gt; &lt;li&gt;&lt;a href="http://www.amazon.com/dp/1590598733"&gt;Amazon&lt;/a&gt;  &lt;li&gt;&lt;a href="http://search.barnesandnoble.com/Accelerated-C-2008/Trey-Nash/e/9781590598733"&gt;Barnes and Noble&lt;/a&gt;  &lt;li&gt;&lt;a href="http://www.apress.com/book/view/1590598733"&gt;Publisher&amp;#39;s page (Apress)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Introduction and disclaimer&lt;/h3&gt; &lt;p&gt;My normal book review disclaimer applies, but probably more so than ever before. Yes, Accelerated C# 2008 is a competitor to C# in Depth. They&amp;#39;re different in many ways, but many people would no doubt be in the target audience for both books. If you meet that criterion, please be aware that as the author of C# in Depth I can&amp;#39;t possibly be 100% objective when reviewing another C# book. That said, I&amp;#39;ll try to justify my opinions everywhere I can.&lt;/p&gt; &lt;h3&gt;Target audience and content overview&lt;/h3&gt; &lt;p&gt;Accelerated C# 2008 is designed to appeal to existing developers with experience in an OO language. As one of the Amazon reviews notes, you may struggle somewhat if you don&amp;#39;t have &lt;em&gt;any&lt;/em&gt; .NET experience beforehand - while it should be possible to read it knowing only Java or C++, there are various times where a certain base level of knowledge is assumed and you&amp;#39;ll want to refer to MSDN for some background material. If you come at the book with no OO experience at all, I expect you&amp;#39;ll have a hard time. Chapter 4 does cover the basics of OO in .NET (classes, structs, methods, properties etc) this isn&amp;#39;t really a beginner&amp;#39;s book.&lt;/p&gt; &lt;p&gt;In terms of actual content covered, Accelerated C# 2008 falls somewhere between C# in Depth (almost purely language) and C# 3.0 in a Nutshell (language and then core libraries). It doesn&amp;#39;t attempt to cover &lt;em&gt;all&lt;/em&gt; the core technologies (IO, reflection, security, interop etc are absent) but it goes into detail beyond the C# language when it comes to strings, exceptions, collections, threading and more. As well as purely factual information, there&amp;#39;s a lot of guidance as well, including a whole chapter entitled &amp;quot;In Search of C# Canonical Forms.&amp;quot;&lt;/p&gt; &lt;h3&gt;General impressions&lt;/h3&gt; &lt;p&gt;I&amp;#39;d like to make it clear to start with that I like the book. I have a number of criticisms, none of which I&amp;#39;m making up for the sake of being critical - but that in no way means it&amp;#39;s a bad book at all. It&amp;#39;s very unlikely that you know everything in here (I certainly didn&amp;#39;t) and the majority of the guidance is sound. The code examples are almost always self-contained (a big plus in my view) and Trey&amp;#39;s style is very readable. Where there are inaccuracies, they&amp;#39;re &lt;em&gt;usually&lt;/em&gt; pretty harmless, and the large amount of accurate and insightful material makes up for them.&lt;/p&gt; &lt;p&gt;Just as I often compare Java to C# in my book, so Trey often compares C++ to C# in his. While my balance of C# to C++ knowledge is such that these comments aren&amp;#39;t particularly useful to me, I can see them being good for a newcomer to C# from a C++ background. I thought there might have been a few too many comparisons (I understood the point about STL and lambdas/LINQ the first time round...) but that&amp;#39;s just a minor niggle.&lt;/p&gt; &lt;p&gt;Where C# in Depth is primarily a &amp;quot;read from start to finish&amp;quot; book and C# 3.0 in a Nutshell is primarily a reference book (both can be used the other way, of course) Accelerated C# 2008 falls between the two. It actually achieves the best of both worlds to a large extent, which is an impressive feat. The ordering could be improved (more on this later on) but the general feeling is very good.&lt;/p&gt; &lt;p&gt;One quick word about the size of the book in terms of content: if you&amp;#39;re one of those people who judges the amount of useful content in a book on its page count, it&amp;#39;s worth noting that the font in this book is pretty small. I would guess that it packs about 25% more text per page than C# in Depth does, taking its &amp;quot;effective&amp;quot; page count from around 500 to 625. Also, the content is certainly meaty - you&amp;#39;re unlikely to find yourself skimming over loads of simple stuff trying to get to the good bits. Speaking of &amp;quot;getting to the good bits&amp;quot; let&amp;#39;s tackle my first significant gripe.&lt;/p&gt; &lt;h3&gt;Material organisation&lt;/h3&gt; &lt;p&gt;If you look at the tables of contents for Accelerated C# 2008 and Accelerated C# 2005, you&amp;#39;ll notice that the exact same chapter titles in the 2005 edition carry over in the same order in the 2008 edition. There are three extra chapters in the new edition, covering extension methods, lambda expressions and LINQ. That&amp;#39;s not to say that the content of the &amp;quot;duplicate&amp;quot; chapters is the same as before - C# 3.0 features are introduced in the appropriate place within existing chapters. In terms of ordering the chapters, I think it would be have been much more appropriate to keep the last chapter of the old edition - &amp;quot;In Search of C# Canonical Forms&amp;quot; - as the last chapter of the new edition. Apart from anything else, that would allow it to include hints and tips involving the new C# 3 features which are currently covered later. It really feels like a &amp;quot;wrapping up&amp;quot; chapter, and deserves to be last.&lt;/p&gt; &lt;p&gt;That&amp;#39;s not the only time that the ordering felt strange, however. Advanced topics (at least ones which feel advanced to me) are mixed in with fairly basic ones. For instance, in the chapter on exceptions, there&amp;#39;s a section about &amp;quot;exception neutrality&amp;quot; which includes details about constrained execution regions and critical finalizers. All interesting stuff - even though I wish there were more of a prominent warning saying, &amp;quot;This is costly to both performance and readability: only go to these lengths when you really, really need to.&amp;quot; However, this comes &lt;em&gt;before&lt;/em&gt; a section about using &lt;code&gt;try&lt;/code&gt;/&lt;code&gt;finally&lt;/code&gt; blocks and the &lt;code&gt;using&lt;/code&gt; statement to make sure that resources are cleaned up however a block is exited. I can&amp;#39;t imagine anyone who knows enough C# to take in the exception neutrality material also &lt;em&gt;not&lt;/em&gt; knowing about try/finally or the using statement (or how to create your own custom exception class, which comes between these two topics).&lt;/p&gt; &lt;p&gt;Likewise the chapter which deals with collections, including generic ones, comes before the chapter on generics. If I were a reader who didn&amp;#39;t know generics already, I think I&amp;#39;d get very confused reading about &lt;code&gt;ICollection&amp;lt;T&amp;gt;&lt;/code&gt; without knowing what the &lt;code&gt;T&lt;/code&gt; meant. Now don&amp;#39;t get me wrong: ordering material so that you don&amp;#39;t get &amp;quot;circular references&amp;quot; is often hard if not impossible. I just think it could have been done better here.&lt;/p&gt; &lt;h3&gt;Aiming too deep?&lt;/h3&gt; &lt;p&gt;It&amp;#39;s not like me to criticise a book for being too deep, but I&amp;#39;m going to make an exception here. Every so often, I came away from a topic thinking that it would have been better covered a little bit more lightly. Sometimes this was because a running example became laborious and moved a long way from anything you were actually likely to want to do in real life. The sections on &amp;quot;borrowing from functional programming&amp;quot; and memoization/currying/anonymous recursion felt guilty of this. It&amp;#39;s not that they&amp;#39;re not interesting topics, but the examples picked didn&amp;#39;t quite work for me.&lt;/p&gt; &lt;p&gt;The other problem with going deep is that you really, really need to get things right - because your readers are less likely to spot the mistakes. I&amp;#39;ll give three examples here:&lt;/p&gt; &lt;ul&gt; &lt;li&gt; &lt;p&gt;Trey works hard on a number of occasions to avoid boxing, and points it out each time. Without any experience in performance tuning, you&amp;#39;d be forgiven for thinking that boxing is the primary cause of poor performance in .NET applications based on this book. While I agree that it&amp;#39;s something to be avoided where it&amp;#39;s possible to do so without bending the design out of shape, it doesn&amp;#39;t deserve to be laboured as much as it is here. In particular, Trey gives an example of a complex number struct and how he&amp;#39;s written appropriate overloads etc to avoid boxing. Unfortunately, to calculate the magnitude of the complex number (used to implement IComparable in a manner which violates the contract, but that&amp;#39;s another matter) he uses &lt;code&gt;Math.Pow(real, 2) + Math.Pow(img, 2)&lt;/code&gt;. Using a quick and dirty benchmark, I found that using &lt;code&gt;real * real + img * img&lt;/code&gt; instead of Math.Pow made &lt;em&gt;far, far&lt;/em&gt; more difference than whether or not the struct was boxed. (I happen to think it&amp;#39;s more readable code too, but never mind.) There was nothing wrong with avoiding the boxing, but in chasing the small performance gains, the big ones were missed.&lt;/p&gt; &lt;li&gt; &lt;p&gt;In the chapter on threading, there are some demonstrations of lock-free programming (&lt;em&gt;before&lt;/em&gt; describing locking, somewhat oddly - and without describing the &lt;code&gt;volatile&lt;/code&gt; modifier). Now, personally I&amp;#39;d want to discourage people from attempting lock-free programming at all unless they&amp;#39;ve got a really good reason (with evidence!) to support that decision - but if you&amp;#39;re going to do it at all, you need to be hugely careful. One of the examples basically has a load of threads starting and stopping, updating a counter (correctly) using &lt;code&gt;Interlocked.Increment&lt;/code&gt;/&lt;code&gt;Decrement&lt;/code&gt;. Another thread monitors the count and periodically reports it - but unfortunately it uses this statement to do it:&lt;/p&gt; &lt;p&gt; &lt;div class="code"&gt;threadCount = Interlocked.Exchange(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; numberThreads, numberThreads); &lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;The explanation states: &amp;quot;Since the &lt;code&gt;Interlocked&lt;/code&gt; class doesn&amp;#39;t provide a method to simply read an &lt;code&gt;Int32&lt;/code&gt; value in an atomic operation, all I&amp;#39;m doing is swapping the &lt;code&gt;numberThreads&lt;/code&gt; variable&amp;#39;s value with its own value, and, as a side effect, the &lt;code&gt;Interlocked.Exchange&lt;/code&gt; method returns to me the value that was in the slot.&amp;quot; Well, not quite. It&amp;#39;s actually swapping the &lt;code&gt;numberThreads&lt;/code&gt; variable&amp;#39;s value with &lt;i&gt;a value evaluated at some point before the method call&lt;/i&gt;. If you rewrite the code like this, it becomes more obviously wrong:&lt;/p&gt; &lt;p&gt; &lt;div class="code"&gt;&lt;span class="ValueType"&gt;int&lt;/span&gt; tmp = numberThreads;&lt;br /&gt;Thread.Sleep(1000); &lt;span class="InlineComment"&gt;// What could possibly happen during this time, I wonder?&lt;/span&gt;&lt;br /&gt;threadCount = Interlocked.Exchange(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; numberThreads, tmp); &lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;The call to &lt;code&gt;Thread.Sleep&lt;/code&gt; is there to make it clear that &lt;code&gt;numberThreads&lt;/code&gt; can very easily change between the initial read and the call to &lt;code&gt;Interlocked.Exchange&lt;/code&gt;. The correct fix to the code is to use something like this:&lt;/p&gt; &lt;p&gt; &lt;div class="code"&gt;threadCount = Interlocked.CompareExchange(&lt;span class="MethodParameter"&gt;ref&lt;/span&gt; numberThreads, 0, 0); &lt;/div&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;That sets &lt;code&gt;numberThreads&lt;/code&gt; atomically to the value 0 if (and only if) its value is &lt;i&gt;already&lt;/i&gt; 0 - in other words, it will never actually change the value, just report it. Now, I&amp;#39;ve laboured the explanation of why the code is wrong because it&amp;#39;s fairly subtle. Obvious errors in books are relatively harmless - subtle ones are much more worrying.&lt;/p&gt; &lt;li&gt; &lt;p&gt;As a final example for this section, let&amp;#39;s look at iterator blocks. Did you know that any parameters passed to methods implemented using iterator blocks become &lt;em&gt;public&lt;/em&gt; fields in the generated class? I certainly didn&amp;#39;t. Trey pointed out that this meant they could easily be changed with reflection, and that could be dangerous. (After looking with reflector, it appears that local variables within the iterator block are also turned into public fields.) Now, leaving aside the fact that this is &lt;em&gt;hugely&lt;/em&gt; unlikely to actually bite anyone (I&amp;#39;d be frankly amazed to see it as a problem in the wild) the suggested fix is very odd. &lt;/p&gt; &lt;p&gt;The example Trey gives is where originally a Boolean parameter is passed into the method, and used in two places. Oh no! The value of the field can be changed between those two uses, which could lead to problems! True. The supposed fix is to wrap the Boolean value in an immutable struct &lt;code&gt;ImmutableBool&lt;/code&gt;, and pass that in instead. Now, why would that be any better? Certainly you can&amp;#39;t change the value within the struct - but you can easily change the &lt;em&gt;field&lt;/em&gt;&amp;#39;s value to be a &lt;em&gt;completely different instance of ImmutableBool&lt;/em&gt;. Indeed, the breakage would involve &lt;em&gt;exactly&lt;/em&gt; the same code, just changing the type of the value. The other train of thought which suggests that this approach would fail is that &lt;code&gt;bool&lt;/code&gt; is &lt;i&gt;already&lt;/i&gt; immutable, so it can&amp;#39;t be the mutability of the &lt;i&gt;type&lt;/i&gt; of the field that causes problems. I&amp;#39;m sure there are much more useful things that Trey could have said in the two and a half pages he spent describing a broken fix to an unimportant problem.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Sorry, that was getting ranty for a bit... but I hope you understand why. Before concluding this review, let&amp;#39;s look at one chapter which is somewhat different to the rest, and which I&amp;#39;ve mentioned before:&lt;/p&gt; &lt;h3&gt;In Search of C# Canonical Forms (aka &amp;quot;Design and Implementation Guidelines&amp;quot; :)&lt;/h3&gt; &lt;p&gt;I&amp;#39;d been looking forward to this part of the book. I&amp;#39;m always interested in seeing what other people think the most important aspects of class design are. The book doesn&amp;#39;t go into much detail about abstract orientation (in this chapter, anyway - there&amp;#39;s plenty scattered through the book) but concentrates on core interfaces you might implement, etc. That&amp;#39;s fine. I&amp;#39;m still waiting for a C# book to be written to truly be on a par with &lt;a href="http://www.amazon.com/dp/0321356683"&gt;Effective Java&lt;/a&gt; (I have the second edition waiting to be read at work...) but I wasn&amp;#39;t expecting it all to be here. So, was this chapter worth the wait?&lt;/p&gt; &lt;p&gt;Somewhat. I was very glad to see that the first point around reference types was &amp;quot;Default to sealed classes&amp;quot; - I couldn&amp;#39;t agree more, and the arguments were well articulated. Many other guidelines were either entirely reasonable or at least I could go either way on. There were a few where I either disagreed or at least would have put things differently:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Implementing cloning with copy constructors: one point about cloning which wasn&amp;#39;t mentioned is that (to quote MSDN) &amp;quot;The resulting clone must be of the same type as or a compatible type to the original instance.&amp;quot; The suggested implementation of &lt;code&gt;Clone&lt;/code&gt; in the book is to use copy constructors. This means that &lt;i&gt;every&lt;/i&gt; subclass must override &lt;code&gt;Clone&lt;/code&gt; to call its own copy constructor, otherwise the instance returned will be of the wrong type. &lt;code&gt;MemberwiseClone&lt;/code&gt; always creates an instance of the same type. Yes, it means the constructor isn&amp;#39;t called - but frankly the example given (performing a database lookup in the constructor) is a pretty dodgy cloning scenario in the first place, in my view. If I create a clone and it doesn&amp;#39;t contain the same data as the original, there&amp;#39;s something wrong. Having said that, the caveats Trey gives around &lt;code&gt;MemberwiseClone&lt;/code&gt; are all valid in and of themselves - we just disagree about their importance. The advice to not actually implement &lt;code&gt;ICloneable&lt;/code&gt; in the first place is also present (and well explained).  &lt;li&gt;Implementing &lt;code&gt;IDisposable&lt;/code&gt;: Okay, so this is a tough topic, but I was slightly disappointed to see the recommendation that &amp;quot;it&amp;#39;s wise for any objects that implement the &lt;code&gt;IDisposable&lt;/code&gt; interface to also implement a finalizer [...]&amp;quot; Now admittedly on the same page there&amp;#39;s the statement that &amp;quot;In reality, it&amp;#39;s rare that you&amp;#39;ll ever need to write a finalizer&amp;quot; but the contradiction isn&amp;#39;t adequately resolved. A lot of people have trouble understanding this topic, so it would have been nice to see really crisp advice here. My 20 second version of it is: &amp;quot;Only implement a finalizer if you&amp;#39;re holding on to resources which won&amp;#39;t be cleaned up by their own finalizers.&amp;quot; That actually cuts out almost everything, unless you&amp;#39;ve got an &lt;code&gt;IntPtr&lt;/code&gt; to a native handle (in which case, use &lt;code&gt;SafeHandle&lt;/code&gt; instead).  &lt;ul&gt; &lt;li&gt;As a side note, Trey repeatedly claims that &amp;quot;finalizers aren&amp;#39;t destructors&amp;quot; which irks me somewhat as the C# spec (the MS version, anyway) uses the word &amp;quot;destructor&amp;quot; exclusively - a destructor is the way you implement a .NET finalizer in C#. It would be fine to say &amp;quot;destructors in C# aren&amp;#39;t deterministic, unlike destructors in C++&amp;quot; but I think it&amp;#39;s worth acknowledging that the word has a valid meaning in the context of C#. Anyway...&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Implementing equality comparisons: while this was largely okay, I was disappointed to see that there wasn&amp;#39;t much discussion of inheritance and how it breaks equality comparisons in a hard-to-fix way. There&amp;#39;s some mention of inheritance, but it doesn&amp;#39;t tackle the issue I think is thorniest: If I&amp;#39;m asking one square whether it&amp;#39;s equal to another square, is it enough to just check for everything I know about squares (e.g. size and position)? What about if one of the squares is actually a &lt;em&gt;coloured&lt;/em&gt; square - it has more information than a &amp;quot;basic&amp;quot; square. It&amp;#39;s very easy to end up with implementations which break reflexivity, simply because the question isn&amp;#39;t well-defined. You effectively need to be asking &amp;quot;are these two objects equal in &amp;lt;this&amp;gt; particular aspect&amp;quot; - but you don&amp;#39;t get to specify the aspect. This is an example where I remember Effective Java (first edition) giving a really thorough explanation of the pitfalls and potential implementations. The coverage in Accelerated C# 2008 is far from &lt;em&gt;bad&lt;/em&gt; - it just doesn&amp;#39;t meet the gold standard. Arguably it&amp;#39;s unfair to ask another book to compete at that level, when it&amp;#39;s trying to do so much else as well.  &lt;li&gt;Ordering: I mentioned earlier on that the complex number class used for a boxing example failed to implement comparisons appropriately. Unfortunately it&amp;#39;s used as the example specifically for &amp;quot;how to implement &lt;code&gt;IComparable&lt;/code&gt; and &lt;code&gt;IComparable&amp;lt;T&amp;gt;&lt;/code&gt;&amp;quot; as well. To avoid going into too much detail, if you have two instances &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; such that &lt;code&gt;x != y&lt;/code&gt; but &lt;code&gt;x.Magnitude == y.Magnitude&lt;/code&gt;, you&amp;#39;ll find &lt;code&gt;x.CompareTo(y) == y.CompareTo(x)&lt;/code&gt; (but with a non-zero result in both cases). What&amp;#39;s needed here is a completely different example - one with a more obvious ordering.  &lt;li&gt;Value types and immutability: Okay, so the last bullet on the value types checklist is &amp;quot;Should this struct be immutable? [...] Values are excellent candidates to be immutable types&amp;quot; but this comes &lt;em&gt;after&lt;/em&gt; &amp;quot;Need to boxed instances of value? Implement an interface to do so [...]&amp;quot; No! Just say no to mutable value types to start with! Mutable value types are bad, bad, bad, and should be avoided like the plague. There are a &lt;em&gt;very&lt;/em&gt; few situations where it &lt;em&gt;may&lt;/em&gt; be appropriate, but to my mind any advice checklist for implementing structs should make two basic points:  &lt;ul&gt; &lt;li&gt;Are you sure you really wanted a struct in the first place? (They&amp;#39;re rarely the right choice.)  &lt;li&gt;Please make it immutable! Pretty please with a cherry on top? Every time a struct is mutated, a cute kitten dies. Do you really want to be responsible for that?&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h3&gt;Conclusion&lt;/h3&gt; &lt;p&gt;At the risk - nay, certainty - of repeating myself, I&amp;#39;m going to say that I like the book despite the (sometimes subjective) flaws pointed out above. As Shakespeare wrote in Julius Caesar, &amp;quot;The evil men do lives after them. The good is oft interred with their bones.&amp;quot; So it is with book reviews - it&amp;#39;s a lot easier to give specific examples of problems than it is to report successes - but the book &lt;em&gt;does&lt;/em&gt; succeed, for the most part. Perhaps the root of almost all my reservations is that it tries to do too much - I&amp;#39;m not sure whether it&amp;#39;s possible to go into that much detail &lt;em&gt;and&lt;/em&gt; cater for those with little or no previous C# experience (even with Java/C++) &lt;em&gt;and&lt;/em&gt; keep to a relatively slim volume. It was a very lofty goal, and Trey has done very well to accomplish what he has. I would be interested to read a book by him (and hey, potentially even collaborate on it) which is &lt;em&gt;solely&lt;/em&gt; on well-designed classes and libraries.&lt;/p&gt; &lt;p&gt;In short, I recommend Accelerated C# 2008, with a few reservations. Hopefully you can judge for yourself whether my reservations would bother you or not. I think overall I &lt;em&gt;slightly&lt;/em&gt; prefer C# 3.0 in a Nutshell, but the two books are fairly different.&lt;/p&gt; &lt;h3&gt;Reaction&lt;/h3&gt; &lt;p&gt;I sent this to Trey before publishing it, as is my custom. He responded to all my points extremely graciously. I&amp;#39;m not sure yet whether I can post the responses themselves - stay tuned for the possibility, at least. My one problem with reviewing books is that I end up in contact with so many other authors who I&amp;#39;d like to work with some day, and that number has just increased again...&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1643045" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Book+reviews/default.aspx">Book reviews</category></item><item><title>Calling Trey Nash...</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/07/23/calling-trey-nash.aspx</link><pubDate>Wed, 23 Jul 2008 18:57:45 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1641914</guid><dc:creator>skeet</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1641914</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1641914</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/07/23/calling-trey-nash.aspx#comments</comments><description>&lt;p&gt;Okay, this is a slightly odd post, but with any luck it&amp;#39;ll prove successful. As I&amp;#39;ve mentioned before, I&amp;#39;m currently reading through Trey Nash&amp;#39;s &amp;quot;Accelerated C# 2008&amp;quot;. I&amp;#39;m writing down errata as I go, but so far the only place I&amp;#39;ve found to leave them is on the Apress web site - which may well be a black hole as far as I know.&lt;/p&gt; &lt;p&gt;So, if anyone knows how to get in touch with Mr Nash, could they either let me know or give him my email address (&lt;a href="mailto:skeet@pobox.com"&gt;skeet@pobox.com&lt;/a&gt;) and ask him to mail me? The normal means of finding him (blogs, forums, personal web sites etc) are failing me at the moment... I&amp;#39;ve left a comment on his blog, but as it&amp;#39;s rarely updated I don&amp;#39;t know whether he&amp;#39;s actively watching it.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Update: Trey has now mailed me, so all is well.&lt;/strong&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1641914" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category></item><item><title>Judging a book by its cover (or title)</title><link>http://msmvps.com/blogs/jon_skeet/archive/2008/07/18/judging-a-book-by-its-cover-or-title.aspx</link><pubDate>Fri, 18 Jul 2008 19:50:24 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1641374</guid><dc:creator>skeet</dc:creator><slash:comments>19</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1641374</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1641374</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2008/07/18/judging-a-book-by-its-cover-or-title.aspx#comments</comments><description>&lt;p&gt;I&amp;#39;ve ranted about versioning before (and indeed in C# in Depth). I still believe that Microsoft didn&amp;#39;t do the world any favours when they introduced a &lt;em&gt;relatively&lt;/em&gt; minor set of changes (just libraries, albeit important ones) with .NET 3.0 and a more major set of changes (languages, LINQ, core library improvements) with .NET 3.5. Using 2.5 and 3.0 would have made more sense, IMO. But never mind.&lt;/p&gt; &lt;p&gt;The fact is, people are confused about what version number applies to what. A number of people claim to be using C# 3.5 when they mean either C# 3.0 or .NET 3.5. (For a quick reference of what&amp;#39;s actually what, see my &lt;a href="http://csharpindepth.com/Articles/Chapter1/Versions.aspx"&gt;article on the issue&lt;/a&gt;.)&lt;/p&gt; &lt;p&gt;Okay, so far it&amp;#39;s the fault of Microsoft for being confusing and the fault of developers for not keeping up. Both of these are far more forgiveable in my view than being &lt;em&gt;flat out wrong&lt;/em&gt; as many books are at the moment. I don&amp;#39;t believe this is any indication on the quality of the book itself (Accelerated C# 2008 is pretty good so far, for example) but I still think it&amp;#39;s pretty awful to make a title so confusing. So, here are some bad titles and others which use version numbers appropriately. (I&amp;#39;ve left out titles like Head First C# and C# in Depth which don&amp;#39;t specify version numbers.)&lt;/p&gt; &lt;h4&gt;Bad&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;Professional C# 2008 (Wrox)&lt;/li&gt; &lt;li&gt;Pro C# 2008 and the .NET 3.5 Platform (Apress) (only partly incorrect, of course)&lt;/li&gt; &lt;li&gt;Murach&amp;#39;s C# 2008 (Mike Murach and Associates)&lt;/li&gt; &lt;li&gt;Accelerated C# 2008 (Apress)&lt;/li&gt; &lt;li&gt;Illustrated C# 2008 (Apress)&lt;/li&gt; &lt;li&gt;Pro LINQ: Language Integrated Query in C# 2008 (APress) &lt;/li&gt; &lt;li&gt;Pro ASP.NET 3.5 in C# 2008 (Apress) (again, only partially incorrect)&lt;/li&gt; &lt;li&gt;Beginning C# 2008 (Apress)&lt;/li&gt; &lt;li&gt;Beginning C# 2008 Databases (Apress)&lt;/li&gt; &lt;li&gt;&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Good&lt;/h4&gt; &lt;ul&gt; &lt;li&gt;C# 3.0 in a Nutshell (O&amp;#39;Reilly)&lt;/li&gt; &lt;li&gt;Programming C# 3.0 (O&amp;#39;Reilly)&lt;/li&gt; &lt;li&gt;C# 3.0 Cookbook (O&amp;#39;Reilly)&lt;/li&gt; &lt;li&gt;C# 3.0 Design Patterns (O&amp;#39;Reilly)&lt;/li&gt; &lt;li&gt;C# 3.0 Pocket Reference (O&amp;#39;Reilly)&lt;/li&gt; &lt;li&gt;Pro C# with .NET 3.0 (Apress)&lt;/li&gt; &lt;li&gt;Beginning C# 3.0 (Wrox)&lt;/li&gt; &lt;li&gt;C# 3.0 Unleashed: With the .NET Framework 3.5 (Sams)&lt;/li&gt;&lt;/ul&gt; &lt;h4&gt;Okay&lt;/h4&gt; &lt;p&gt;This is the &amp;quot;well, just about&amp;quot; list - because they&amp;#39;re referring to &amp;quot;Microsoft Visual C# 2008&amp;quot; instead of C# 2008, it&amp;#39;s referring to the IDE instead of the language. I think it&amp;#39;s better to name a book after the language instead of the tool you use to write in the language, personally...&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Beginning Microsoft Visual C# 2008 (Wrox)&lt;/li&gt; &lt;li&gt;Microsoft Visual C# 2008 Step By Step (Microsoft)&lt;/li&gt; &lt;li&gt;Programming Microsoft Visual C# 2008 (Microsoft)&lt;/li&gt; &lt;li&gt;Microsoft Visual C# 2008 Express Edition: Build a Program Now! (Microsoft)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Notice a pattern? If anyone at Apress is reading this (unlikely, I know) - &lt;em&gt;there&amp;#39;s no such thing as &lt;/em&gt;&amp;quot;&lt;em&gt;C# 2008&lt;/em&gt;&amp;quot;.&lt;/p&gt; &lt;p&gt;Rant over for the moment. With any luck I might be able to finish reading Accelerated C# 2008 fairly soon, and give a proper book review.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1641374" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Books/default.aspx">Books</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Book+reviews/default.aspx">Book reviews</category></item></channel></rss>