<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fabulous Adventures In Coding : C# 4.0</title><link>http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx</link><description>Tags: C# 4.0</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Exact rules for variance validity</title><link>http://blogs.msdn.com/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx</link><pubDate>Thu, 03 Dec 2009 14:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9923708</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9923708.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9923708</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I thought it might be interesting for you all to get a precise description of how exactly it is that we determine when it is legal to put "in" and "out" on a type parameter declaration in C# 4. I'm doing this here because (1) it's of general interest, and (2) our attempt to make a more human-readable version of this algorithm in the draft C# 4.0 specification accidentally introduced some subtle errors. We're working on correcting those errors for the final release of the specification; until then, &lt;EM&gt;these definitions are the definitions I actually worked from to do the implementation&lt;/EM&gt;, so they're accurate. &lt;/P&gt;
&lt;P&gt;These definitions are pretty much stolen straight from the CLI spec section on variance; I am indebted to its authors for their careful and precise definitions.&lt;/P&gt;
&lt;P&gt;The first things we need to define are three kinds of "validity" for &lt;STRONG&gt;types&lt;/STRONG&gt;. I want to define "valid covariantly", "valid contravariantly" and "valid invariantly", but only as applied to &lt;STRONG&gt;types&lt;/STRONG&gt;. We'll talk about what makes an interface &lt;STRONG&gt;declaration&lt;/STRONG&gt; a valid one later; we need these definitions first.&lt;/P&gt;
&lt;P&gt;Before we get into a precise definition, I want to talk about what "valid covariantly" means logically. The idea that we are attempting to capture here boils down to "the type we're talking about is &lt;EM&gt;not contravariant&lt;/EM&gt;". Whether it is &lt;EM&gt;covariant&lt;/EM&gt;, we don't really care. All we care about it is that &lt;STRONG&gt;if it is valid covariantly, then it is not contravariant&lt;/STRONG&gt;. Similarly, by "valid contravariantly", we mean "not covariant".&lt;/P&gt;
&lt;P&gt;This leads us to our first brain-hurting definition: A type is "&lt;STRONG&gt;valid invariantly&lt;/STRONG&gt;"&amp;nbsp;if it is &lt;STRONG&gt;both&lt;/STRONG&gt; valid covariantly and valid contravariantly. That sounds a bit crazy -- how can it be valid invariantly if it is both covariant and contravariant? But "valid covariantly" does not mean "is covariant", it means "it's guaranteed to not be contravariant".&amp;nbsp;So if a type is valid covariantly and valid contravariantly, then it is guaranteed to be neither contravariant nor covariant, and therefore must be invariant.&lt;/P&gt;
&lt;P&gt;Anyway. We want to take any specific type and classify it as valid covariantly, valid contravariantly, or both, a.k.a., valid invariantly. (We don't need to worry about coming up with a term for the "or none of the above" case because in practice that case is never relevant.)&lt;/P&gt;
&lt;P&gt;A type is &lt;STRONG&gt;valid covariantly&lt;/STRONG&gt; if it is:&lt;/P&gt;
&lt;P&gt;1) a class, struct, nullable, enum, pointer, non-generic delegate or non-generic interface type.&lt;/P&gt;
&lt;P&gt;This should make sense. Remember, what we're getting at is "not contravariant". Classes and structs are either non-generic, in which case they are clearly not contravariant, or they are generic, in which case again they are not contravariant because we do not support variance on classes or structs.&amp;nbsp;Nullable types are just aliases for Nullable&amp;lt;T&amp;gt; which is a struct type, and therefore not variant. Enums&amp;nbsp;and pointers are non-generic so they are not variant. And non-generic delegates and interfaces are by definition not generic and therefore not variant either.&amp;nbsp;These&amp;nbsp;are the easy cases.&lt;/P&gt;
&lt;P&gt;2) An array type T[] where T is valid covariantly.&lt;/P&gt;
&lt;P&gt;Because we have array covariance in C#, but not array contravariance, we can make arrays valid covariantly. Again, remember, "valid covariantly" means "not contravariant".&lt;/P&gt;
&lt;P&gt;3) A generic type parameter type, if it was not declared as being contravariant.&lt;/P&gt;
&lt;P&gt;Generic type parameter types are of course types as far as the compiler is concerned. If you're inside the declaration of a generic interface then you can use its type parameters as types. In that context, such types are valid covariantly if they were not declared as contravariant (in).&lt;/P&gt;
&lt;P&gt;4) A constructed interface or delegate type X&amp;lt;T1, ... Tk&amp;gt; might be valid covariantly. To determine if it is, we examine each type argument differently, depending on whether the corresponding type parameter was declared as covariant (out), contravariant (in), or invariant (neither). If the ith&amp;nbsp;type parameter was declared as covariant, then Ti must be valid covariantly. If it was declared as contravariant, then Ti must be valid contravariantly. If it was declared as invariant, then Ti must be valid invariantly. &lt;/P&gt;
&lt;P&gt;As one would expect, covariant validity preserves the direction of validity; covariant parameters must be valid covariantly, contravariant parameters must be valid contravariantly.&lt;/P&gt;
&lt;P&gt;OK, I hope that was relatively painless. The rules for contravariant validity are similar; as one would expect from the "backwards" nature of contravariance, the directions are reversed in the complicated case:&lt;/P&gt;
&lt;P&gt;A type is &lt;STRONG&gt;valid contravariantly&lt;/STRONG&gt; if it is:&lt;/P&gt;
&lt;P&gt;1) a class, struct, nullable, enum, pointer, non-generic delegate or non-generic interface type.&lt;/P&gt;
&lt;P&gt;2) An array type T[] where T is valid contravariantly.&lt;/P&gt;
&lt;P&gt;Arrays are covariant in their element type. Covariance preserves the direction of variance. Therefore, to be valid contravariantly, an array (covariant in its element type) must be contravariantly valid in its element type.&lt;/P&gt;
&lt;P&gt;3) A generic type parameter type, if it was not declared as being covariant.&lt;/P&gt;
&lt;P&gt;Remember, "valid contravariantly" means "not covariant". It does not mean "contravariant".&lt;/P&gt;
&lt;P&gt;4) A constructed interface or delegate type X&amp;lt;T1, ... Tk&amp;gt; might be valid contravariantly. If the ith&amp;nbsp;type parameter was declared as contravariant, then Ti must be valid covariantly. If it was declared as covariant, then Ti must be valid contravariantly. If it was declared as invariant, then Ti must be valid invariantly. &lt;/P&gt;
&lt;P&gt;As one might expect, contravariant validity &lt;EM&gt;reverses&lt;/EM&gt; the direction of validity. &lt;/P&gt;
&lt;P&gt;Now perhaps you see why we wanted to rewrite these definitions into something more human-readable for the spec. And perhaps you also see why we accidentally introduced errors in doing so; bending your brain around all this logic is not always easy.&lt;/P&gt;
&lt;P&gt;OK, now that we've got that, we can make a definition of what it means for an interface to be valid. An interface must meet the following conditions:&lt;/P&gt;
&lt;P&gt;* The return types of&amp;nbsp;all non-void interface methods must be valid covariantly.&lt;/P&gt;
&lt;P&gt;* Every formal parameter type of&amp;nbsp;all interface methods must be valid contravariantly. (Invariantly if it is an out or ref parameter.)&lt;/P&gt;
&lt;P&gt;* For all generic methods on an interface,&amp;nbsp;every constraint on the generic method type parameters must be valid contravariantly.&lt;/P&gt;
&lt;P&gt;* All its base interface types&amp;nbsp;must be&amp;nbsp;valid covariantly.&lt;/P&gt;
&lt;P&gt;* The type of a property or indexer must be valid covariantly if it has a "getter" and valid contravariantly if it has a "setter".&lt;/P&gt;
&lt;P&gt;* Any formal parameter types of an indexer must be valid contravariantly.&lt;/P&gt;
&lt;P&gt;* The delegate types of all its events must be valid contravariantly.&lt;/P&gt;
&lt;P&gt;The first two are pretty straightforward; return types "go out" so they have to be valid covariantly, formal parameter types "go in", so they have to be valid contravariantly. But what's up with the third one? What do constraints on generic method type parameters have to do with interface validity?&lt;/P&gt;
&lt;P&gt;Well, let's suspend&amp;nbsp;the third rule&amp;nbsp;and see what goes wrong.&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface I&amp;lt;out T&amp;gt;&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M&amp;lt;U&amp;gt;() where U : T; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // illegal; this has to be valid contravariantly but it is a covariant type parameter constraint.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Let it ride for now and demonstrate an error.&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;class C&amp;lt;T&amp;gt; : I&amp;lt;T&amp;gt; { public void M&amp;lt;U&amp;gt;() {} }&lt;BR&gt;// the constraint is inherited implicitly and not re-stated.&lt;/P&gt;
&lt;P&gt;I&amp;lt;Giraffe&amp;gt; igiraffe = new C&amp;lt;Giraffe&amp;gt;();&amp;nbsp;// C&amp;lt;T&amp;gt; implements I&amp;lt;T&amp;gt;&lt;BR&gt;I&amp;lt;Animal&amp;gt; ianimal = igiraffe; // interface is covariant in T&lt;BR&gt;ianimal.M&amp;lt;Turtle&amp;gt;(); // satisifies the constraint that U must be an Animal.&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Uh oh. ianimal is really an instance of&amp;nbsp;C&amp;lt;Giraffe&amp;gt;.&amp;nbsp;The M&amp;lt;U&amp;gt; method on C&amp;lt;Giraffe&amp;gt; inherits a requirement that U inherit from Giraffe. Turtle does not inherit from Giraffe. Therefore we've just violated the constraint on M&amp;lt;U&amp;gt;. The only places where we can catch this is in the declaration; every other step is&amp;nbsp;perfectly legal. Therefore, a constraint cannot be covariant. But if we make it contravariant (or invariant) then it all works out. For example, let's make a contravariant type parameter constraint:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface I2&amp;lt;in T&amp;gt; // contravariant this time&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M&amp;lt;U&amp;gt;() where U : T; &lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;class C2&amp;lt;T&amp;gt; : I2&amp;lt;T&amp;gt; { public void M&amp;lt;U&amp;gt;() {} }&lt;BR&gt;I2&amp;lt;Animal&amp;gt; i2animal = new C2&amp;lt;Animal&amp;gt;();&amp;nbsp;// C2&amp;lt;T&amp;gt; implements I2&amp;lt;T&amp;gt;&lt;BR&gt;I2&amp;lt;Mammal&amp;gt; i2mammal = i2animal; // interface is contravariant in T&lt;BR&gt;i2mammal.M&amp;lt;Giraffe&amp;gt;(); // satisifies the constraint that U must be an Animal.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;And now everything is fine; the compile-time constraint checker verifies that Giraffe is Mammal; at runtime it must be Animal,&amp;nbsp;and so the compiler has verified that by verifying that&amp;nbsp;it is Mammal.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The rules for &lt;STRONG&gt;delegate declarations&lt;/STRONG&gt; are a straightforward simplification of the rules for interface declarations. To be a valid delegate declaration, the return type must be valid covariantly (or void), the formal parameter types must be valid contravariantly (or invariantly if they are out/ref), and any type parameter constraints must be valid contravariantly. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9923708" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx">Covariance and Contravariance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category></item><item><title>What's the difference between covariance and assignment compatibility?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx</link><pubDate>Mon, 30 Nov 2009 14:51:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9923199</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>18</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9923199.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9923199</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I've written a lot about this already, but I think one particular point bears repeating.&lt;/P&gt;
&lt;P&gt;As we're getting closer to shipping C# 4.0, I'm seeing a lot of documents, blogs, and so on, attempting to explain what "covariant" means. This is a tricky word to define in a way that is actually meaningful to people who haven't already got degrees in category theory, but it can be done. And I think it's important to avoid defining a word to mean something other than its actual meaning.&lt;/P&gt;
&lt;P&gt;A number of those documents have led with something like:&lt;/P&gt;
&lt;P&gt;"Covariance is the ability to assign an expression of a more specific type to a variable of a less specific type. For example, consider a method M that returns a Giraffe. You can assign the result of M to a variable of type Animal, because Animal is a less specific type that is compatible with Giraffe. Methods in C# are 'covariant' in their return types, which is why when you create a covariant interface, it is indicated with the keyword 'out' -- the returned value comes 'out' of the method."&lt;/P&gt;
&lt;P&gt;But that's &lt;STRONG&gt;not at all&lt;/STRONG&gt; what covariance means. That's describing "assignment compatibility" -- the ability to assign a value of a more specific type to a storage of a compatible, less specific type is called "assignment compatibility" because the two types are compatible for the purposes of verifying legality of assignments.&lt;/P&gt;
&lt;P&gt;So what does covariance mean then?&lt;/P&gt;
&lt;P&gt;First off, we need to work out precisely what the adjective "covariant" applies to. I'm going to get more formal for a bit here, but try to keep it understandable.&lt;/P&gt;
&lt;P&gt;Let's start by not even considering types. Let's think about integers. (And here I am speaking of actual mathematical integers, not of the weird behaviour of 32-bit integers in unchecked contexts.) Specifically, we're going to think about the ≤ relation on integers, the "less than or equal to" relation. (Recall that of course a "relation" is a function which takes two things and returns a bool which indicates whether the given relationship holds or does not hold.)&lt;/P&gt;
&lt;P&gt;Now let's think about a projection on integers. What is a projection? A projection is a function which takes a single integer and returns a new integer. So, for example, z → z + z is a projection; call it D for "double".&amp;nbsp; So are z → 0 - z, N for "negate" and z → z * z, S for "square".&lt;/P&gt;
&lt;P&gt;Now, here's an interesting question. Is it always the case that (x ≤ y) = (D(x) ≤ D(y))?&amp;nbsp; Yes, it is. If x is less than y, then twice x is less than twice y. If x is equal to y then twice x is equal to twice y. And if x is greater than y, then twice x is greater than twice y. The projection D preserves the direction of size.&lt;/P&gt;
&lt;P&gt;What about N? Is it always the case that (x ≤ y) = (N(x) ≤ N(y))?&amp;nbsp; Clearly not. 1 ≤ 2 is true, but -1 ≤ -2 is false. But we notice that the reverse is always true!&amp;nbsp; (x ≤ y) = (N(y) ≤ N(x)). The projection N reverses the direction of size.&lt;/P&gt;
&lt;P&gt;What about S? Is it always the case that (x ≤ y) = (S(x) ≤ S(y))? No. -1 ≤ 0 is true, but S(-1) ≤ S(0) is false. What about the opposite? Is it always the case that (x ≤ y) = (S(y) ≤ S(x)) ? Again, no. 1 ≤ 2 is true, but S(2) ≤ S(1) is false. The projection S does not preserve the direction of size, and nor does it reverse it. &lt;/P&gt;
&lt;P&gt;The projection D is "covariant" -- it preserves the ordering relationship on integers. The projection N is "contravariant". It reverses the ordering relationship on integers. The projection S does neither; it is "invariant".&lt;/P&gt;
&lt;P&gt;Now I hope it is more clear exactly what is covariant or contravariant. The integers themselves are not variant, and the "less than" relationship is not variant. It's &lt;STRONG&gt;the projection&lt;/STRONG&gt; that is covariant or contravariant -- the rule for taking an old integer and making a new one out of it.&lt;/P&gt;
&lt;P&gt;So now lets abandon integers and think about reference types. Instead of the ≤ relation on integers, we have the ≤ relation on reference types. A reference type X is smaller than (or equal to) a reference type Y if a value of type X can be stored in a variable of type Y. That is, if X is "assignment compatible" with Y.&lt;/P&gt;
&lt;P&gt;Now consider a projection from types to types. Say, the projection "T goes to IEnumerable&amp;lt;T&amp;gt;".&amp;nbsp; That is, we have a projection that takes a type, say, Giraffe, and gives you back a new type, IEnumerable&amp;lt;Giraffe&amp;gt;. Is that projection covariant in C# 4?&amp;nbsp; Yes. It preserves the direction of ordering. A Giraffe may be assigned to a variable of type Animal, and therefore an sequence of Giraffes may be assigned to a variable that can hold a sequence of Animals.&lt;/P&gt;
&lt;P&gt;We can think of generic types as "blueprints" that produce constructed types. Let's take the projection that takes a type T and produces IEnumerable&amp;lt;T&amp;gt; and simply call that projection "IEnumerable&amp;lt;T&amp;gt;". We can understand from context when we say "IEnumerable&amp;lt;T&amp;gt; is covariant" what we mean is "the projection which takes a reference type T and produces a reference type IEnumerable&amp;lt;T&amp;gt; is a covariant projection". And since IEnumerable&amp;lt;T&amp;gt; only has one type parameter, it is clear from the context that we mean that the parameter to the projection is T. After all, it is a lot shorter to say "IEnumerable&amp;lt;T&amp;gt; is covariant" than that other mouthful.&lt;/P&gt;
&lt;P&gt;So now we can define covariance, contravariance and invariance. A generic type I&amp;lt;T&amp;gt; is &lt;STRONG&gt;covariant&lt;/STRONG&gt; (in T) if construction with reference type arguments &lt;STRONG&gt;preserves&lt;/STRONG&gt; the direction of assignment compatibility. It is &lt;STRONG&gt;contravariant&lt;/STRONG&gt; (in T) if it &lt;STRONG&gt;reverses&lt;/STRONG&gt; the direction of assignment compatibility. And it is &lt;STRONG&gt;invariant&lt;/STRONG&gt; if it does neither. And by that, we simply are saying in a concise way that the &lt;STRONG&gt;projection&lt;/STRONG&gt; which takes a T and produces I&amp;lt;T&amp;gt; is a covariant/contravariant/invariant projection.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;UPDATE: My close personal friend (and fellow computer geek)&amp;nbsp;Jen notes that in the Twilight series of novels, the so-called "werewolves" (who are not transformed by the full moon and therefore not actually werewolves) maintain their rigid social ordering in both wolf and human form; the projection from human to wolf is covariant in the social-ordering relation. She also notes that in high school, programming language geeks are at the bottom of the social order, but the projection to adulthood catapults them to the top of the social order, and therefore, growing up is contravariant. I am somewhat skeptical of the latter claim; the former, I'll take your word for it. I suppose the question of how social order works amongst teenage werewolves who are computer geeks is a subject for additional research. Thanks Jen!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9923199" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Rarefied+Heights/default.aspx">Rarefied Heights</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx">Covariance and Contravariance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/What_2700_s+The+Difference_3F00_/default.aspx">What's The Difference?</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/werewolves/default.aspx">werewolves</category></item><item><title>The Purpose, Revealed</title><link>http://blogs.msdn.com/ericlippert/archive/2009/11/25/the-purpose-revealed.aspx</link><pubDate>Wed, 25 Nov 2009 17:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9928668</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9928668.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9928668</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Interestingly enough, no one correctly guessed why I needed code in the compiler to transform a method argument list into a form that batched up the side effecting expressions, stuck their values in variables, and then called the method with the side-effect-free variable references. There certainly were some fascinating ideas in the comments though!&lt;/P&gt;
&lt;P&gt;The reason is quite mundane. We had a bug in the code that performs semantic analysis of calls with named arguments. One of our rules in C# that I've talked about a lot on this blog is that sub-expression evaluation occurs in left-to-right order. If you have a method &lt;SPAN class=code&gt;void&amp;nbsp;M(int&amp;nbsp;x,&amp;nbsp;int&amp;nbsp;y)&amp;nbsp;{} &lt;/SPAN&gt;and then a call site &lt;SPAN class=code&gt;M(y&amp;nbsp;:&amp;nbsp;F(),&amp;nbsp;x&amp;nbsp;:&amp;nbsp;G());&lt;/SPAN&gt; we cannot simply generate the code as though you'd written &lt;SPAN class=code&gt;M(G(),&amp;nbsp;F())&lt;/SPAN&gt;. The side effects of F have to happen before the side effects of G, so we generate code as though you'd said &lt;SPAN class=code&gt;temp1&amp;nbsp;=&amp;nbsp;F(); temp2&amp;nbsp;=&amp;nbsp;G(); M(y&amp;nbsp;:&amp;nbsp;temp1,&amp;nbsp;x&amp;nbsp;:&amp;nbsp;temp2);&lt;/SPAN&gt; and now we can generate the call as &lt;SPAN class=code&gt;M(temp2,&amp;nbsp;temp1);&lt;/SPAN&gt; without worrying about re-ordering a side effect. &lt;/P&gt;
&lt;P&gt;The bug was that the rewriter was not getting the reordering correct if the parameters were ref/out or the arguments were locals without side effects. As I often do when fixing a bug, I reasoned that the initial bug had been caused because the rewriter was under-specified. &lt;/P&gt;
&lt;P&gt;The fix will get into the initial release of C# 4, but the problems that Pavel identified with it -- that certain obscure side effects such as the order in which bad array accesses throw exceptions, or the order in which static class constructors execute, are not correctly preserved by my algorithm, will not be fixed for the initial release. Doing these correctly requires us to be able to generate temporaries of "reference to argument" types, which we've never done before and which our IL generator was not built to handle. Had we discovered the bug much earlier in the cycle, we probably could have applied a more solid fix, but it is too late now. &lt;/P&gt;
&lt;P&gt;Thanks again to Pavel for the great analysis, and thanks to our old friend nikov for reporting the bug in the first place. &lt;/P&gt;
&lt;P&gt;And happy thanksgiving to my readers in the United States! As I do every year, I'm roasting a turkey to feed fourteen people. I highly recommend the "brine the bird then&amp;nbsp;roast it upside-down" method described in The Joy Of Cooking. It's worked perfectly&amp;nbsp;for me for the last ten years straight.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9928668" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Code+Generation/default.aspx">Code Generation</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Software+development+methodology/default.aspx">Software development methodology</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/named+parameters/default.aspx">named parameters</category></item><item><title>Some new videos</title><link>http://blogs.msdn.com/ericlippert/archive/2009/10/26/some-new-videos.aspx</link><pubDate>Mon, 26 Oct 2009 13:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9911473</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9911473.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9911473</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Somehow it has happened again; people just keep on recording videos of me and putting them on the internet. &lt;/P&gt;
&lt;P&gt;In these videos you find out what I look like when lit from above and behind. Kinda spooky. We should have made the room entirely dark and held a flashlight underneath my face. That would be, like, &lt;A class="" href="http://xenon.xe.net/inthumor/ih_026.htm" mce_href="http://xenon.xe.net/inthumor/ih_026.htm"&gt;ten times scarier&lt;/A&gt;. Anyway, if you're interested in me blathering on about my favourite feature in C# 4, covariance and contravariance of interface and delegate types, here are two little demo videos: &lt;A class="" href="http://msdn.microsoft.com/en-us/vcsharp/ee672314.aspx" mce_href="http://msdn.microsoft.com/en-us/vcsharp/ee672314.aspx"&gt;Part One&lt;/A&gt;, &lt;A class="" href="http://msdn.microsoft.com/en-us/vcsharp/ee672319.aspx" mce_href="http://msdn.microsoft.com/en-us/vcsharp/ee672319.aspx"&gt;Part Two&lt;/A&gt;. (There seems to be some minor sound sync issues here and there, but it's not really a problem; most of the&amp;nbsp;audio is voice-over.)&lt;/P&gt;
&lt;P&gt;Charlie has been crazy busy getting these little videos together; here are some more of his recent efforts, including some good ones from my colleagues Chris and Sam talking about all the other far more awesome features of C# 4.0: dynamic interop, improved interop with Office, named and optional parameters, and so on. Links to all of our recent videos are here: &lt;A href="http://blogs.msdn.com/charlie/archive/2009/10/19/community-convergence-lvi.aspx" mce_href="http://blogs.msdn.com/charlie/archive/2009/10/19/community-convergence-lvi.aspx"&gt;http://blogs.msdn.com/charlie/archive/2009/10/19/community-convergence-lvi.aspx&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Have an amusing and safe Hallowe'en -- I'll be going to Hallowe'en parties on a small island this year, just for a change of pace.&lt;/P&gt;
&lt;P mce_keep="true"&gt;[Eric is on vacation this week; this posting was pre-recorded]&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9911473" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx">Video</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx">Covariance and Contravariance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>Why No Extension Properties?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/10/05/why-no-extension-properties.aspx</link><pubDate>Mon, 05 Oct 2009 16:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9899167</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9899167.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9899167</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I'm frequently asked "you guys added extension methods to C# 3, so why not add extension properties as well?"&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Good question.&lt;/P&gt;
&lt;P&gt;First, let me talk a bit about C# 3. Clearly the big feature in C# 3 was LINQ. In a sense we had only three features in C# 3:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;everything necessary for LINQ -- implicitly typed locals, anonymous types, lambda expressions, extension methods, object and collection initializers, query comprehensions, expression trees, improved method type inference&lt;/LI&gt;
&lt;LI&gt;partial methods&lt;/LI&gt;
&lt;LI&gt;automatically implemented&amp;nbsp;properties&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The latter two were&amp;nbsp;tiny compared to the&amp;nbsp;items in that&amp;nbsp;first bucket. On the design side, the syntax and semantics of both features are straightforward. On the implementation side, we already had the mechanisms in place to remove a call site; partial methods and conditional methods are pretty much the same thing behind the scenes. Auto props were also straightforward to analyze and generate code for. The testing burden was not particularly&amp;nbsp;large for these features either.&lt;/P&gt;
&lt;P&gt;The C# team was "the long pole" for the 2008 release of Visual Studio and the .NET Framework. By that I mean that if you took the amount of time required to do the work&amp;nbsp;each team signed up for, given our level of staffing, blah blah blah, and made a pole proportionally long for each team in Developer Division, the C# pole would have been the longest pole. Which means that every other team in devdiv had slack in their schedule, but&amp;nbsp;if we slipped our schedule a day,&amp;nbsp;the new VS/CLR&amp;nbsp;would also ship a day late. If any other team slipped a day, well, as long as that didn't make their pole longer than ours, they were still OK. Within the team, dividing up the work amongs the various development team members, the "long pole" work was the lambda binding and method type inference work, which was mine. So in a sense, every day that I was late, we'd slip the whole product that many days. (No pressure!)&lt;/P&gt;
&lt;P&gt;Fortunately we have an excellent team here, we all supported each other very well through that release, picked up each other's slack when necessary, and delivered a quality release in plenty of time. My point is&amp;nbsp;simply that &lt;STRONG&gt;unless a feature was either necessary for LINQ, or small and orthogonal and easy to cut if necessary (like the other two), it got cut immediately&lt;/STRONG&gt;. There was no way we were going to risk slipping the entire product for any feature that was both &lt;EM&gt;complex&lt;/EM&gt; and &lt;EM&gt;unnecessary&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;It was of course immediately obvious that the natural companion to extension methods is extension properties. It's less obvious, for some reason, that extension events, extension operators, extension constructors (also known as "the factory pattern"), and so on, are also natural companions. But we didn't even &lt;EM&gt;consider&lt;/EM&gt; designing extension properties for C# 3; we knew that they were not necessary and would add risk to an already-risky schedule for no compelling gain. &lt;/P&gt;
&lt;P&gt;So now we come to C# 4. &lt;/P&gt;
&lt;P&gt;As I'm fond of pointing out, the answer to every question of the form "why doesn't product X have&amp;nbsp;feature Y?" is the same.&amp;nbsp;It's because in order for a product to have a feature, that feature must be:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;thought of in the first place&lt;/LI&gt;
&lt;LI&gt;desired&lt;/LI&gt;
&lt;LI&gt;designed&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;specified&lt;/LI&gt;
&lt;LI&gt;implemented&lt;/LI&gt;
&lt;LI&gt;tested&lt;/LI&gt;
&lt;LI&gt;documented&lt;/LI&gt;
&lt;LI&gt;shipped to customers&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;You've got to hit every single one of those things,&amp;nbsp;otherwise, no feature.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When we started working on C# 4, we made a list of every feature request we'd heard of. It had hundreds of features on it. &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2008/10/08/the-future-of-c-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2008/10/08/the-future-of-c-part-one.aspx"&gt;As I described last year&lt;/A&gt;, we categorized that list into "gotta have / nice to have / bad idea" buckets. Extension properties were in the "gotta have" bucket. We then looked at our available budget -- which was not so much measured in dollars as in available designers, developers, testers, writers and management multiplied by available time -- and determined that we did not have the resources to do more than about half the things in the "gotta have" bucket. So we cut half that stuff. Extension properties made it past that cut.&lt;/P&gt;
&lt;P&gt;We then designed the feature. We had many hours of debate about the proposed syntax on the declaration side, how to call an extension property getter or setter "directly" as a static method, and so on. We came up with a syntax we could agree was acceptable, designed the semantics, wrote up a draft specification, and started writing code and test plans.&lt;/P&gt;
&lt;P&gt;By the time the code was in reasonable shape -- not yet seriously tested, but usable and compliant with the spec -- we'd been having meetings with the WPF team. WPF developers&amp;nbsp;were the assumptive primary consumers of extension properties. WPF&amp;nbsp;already has a mechanism that resembles extension properties; it would be nice to unify that mechanism with our mechanism. Unfortunately, after taking a deep look at their real-world scenarios, we came to the disappointing conclusion that we had designed the wrong thing; this was not actually a feature that would solve their problems.&lt;/P&gt;
&lt;P&gt;This is, admittedly, in a sense a failure of the design process. In retrospect, we should have gotten input and feedback from the primary customer much earlier. Had we done that then they could have either influenced the design to make something that would work for them, or we could have cut the feature without taking on the expense of writing spec, code and test plans. &lt;/P&gt;
&lt;P&gt;But when you're in an unfortunate situation, you've got to decide to stop throwing good money after bad. Rather than take on the additional costs -- testing, documentation, shipping, and then maintenance of the feature for the rest of the life of the language -- in exchange for a feature that did not serve the needs of our customers, we cut the feature. At that point we did not feel confident that we had enough cycles remaining to redesign the feature the right way.&lt;/P&gt;
&lt;P&gt;Therefore, sadly, no extension properties in C# 4. Perhaps in a hypothetical future version of C#.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9899167" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/extension+properties/default.aspx">extension properties</category></item><item><title>What's the difference, part one: Generics are not templates</title><link>http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx</link><pubDate>Thu, 30 Jul 2009 16:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9803982</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>32</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9803982.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9803982</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Because I'm a geek, I enjoy&amp;nbsp;learning about the sometimes-subtle differences between easily-confused things. For example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I'm still not super-clear in my head on the differences between a &lt;STRONG&gt;hub&lt;/STRONG&gt;, &lt;STRONG&gt;router&lt;/STRONG&gt; and &lt;STRONG&gt;switch&lt;/STRONG&gt; and how it relates to the gnomes that live inside of each.&lt;/LI&gt;
&lt;LI&gt;Hunks of minerals found in nature are &lt;STRONG&gt;rocks&lt;/STRONG&gt;; as soon as you put them in a garden or build a bridge out of them, suddenly they become &lt;STRONG&gt;stones&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;When a &lt;STRONG&gt;pig&lt;/STRONG&gt; hits 120 pounds, it's a &lt;STRONG&gt;hog&lt;/STRONG&gt;.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I thought I might do an occasional series on easily confounded concepts in programming language design.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here’s a question I get fairly often:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public static void DoIt&amp;lt;T&amp;gt;(T t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReallyDoIt(t);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(string s)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("string");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt&amp;lt;T&amp;gt;(T t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("everything else");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What happens when you call &lt;SPAN class=code&gt;C.DoIt&amp;lt;string&amp;gt;&lt;/SPAN&gt;? Many people expected that “string” is printed, when in fact “everything else” is always printed, no matter what T is. &lt;/P&gt;
&lt;P&gt;The C# specification says that when you have a choice between calling &lt;SPAN class=code&gt;ReallyDoIt&amp;lt;string&amp;gt;(string)&lt;/SPAN&gt; and &lt;SPAN class=code&gt;ReallyDoIt(string)&lt;/SPAN&gt; – that is, when the choice is between two methods that have identical signatures, but one gets that signature via generic substitution – then we pick the “natural” signature over the “substituted” signature. Why don’t we do that in this case?&lt;/P&gt;
&lt;P&gt;Because that’s not the choice that is presented. If you had said&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;ReallyDoIt("hello world");&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;then we would pick the “natural” version. But you didn’t pass something known to the compiler to be a string. You passed something known to be a T, an unconstrained type parameter, and hence it could be anything. So, the overload resolution algorithm reasons, is there a method that can always take anything? Yes, there is. &lt;/P&gt;
&lt;P&gt;This illustrates that &lt;STRONG&gt;generics&lt;/STRONG&gt; in C# are not like &lt;STRONG&gt;templates&lt;/STRONG&gt; in C++. You can think of templates as a fancy-pants search-and-replace mechanism. When you say &lt;SPAN class=code&gt;DoIt&amp;lt;string&amp;gt;&lt;/SPAN&gt; in a template, the compiler conceptually searches out all uses of “T”, replaces them with “string”, and then compiles the resulting source code. Overload resolution proceeds with the substituted type arguments known, and the generated code then reflects the results of that overload resolution.&lt;/P&gt;
&lt;P&gt;That’s not how generic types work; generic types are, well, &lt;EM&gt;generic&lt;/EM&gt;. We do the overload resolution &lt;STRONG&gt;once&lt;/STRONG&gt; and bake in the result. We do not change it at runtime when someone, possibly in an entirely different assembly, uses string as a type argument to the method. The IL we’ve generated for the generic type already has the method its going to call picked out. The jitter does not say “well, I happen to know that if we asked the C# compiler to execute right now with this additional information then it would have picked a different overload. Let me rewrite the generated code to ignore the code that the C# compiler originally generated...” The jitter knows nothing about the rules of C#.&lt;/P&gt;
&lt;P&gt;Essentially, the case above is no different from this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public static void DoIt(object t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReallyDoIt(t);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(string s)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("string");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(object t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("everything else");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;When the compiler generates the code for the call to &lt;SPAN class=code&gt;ReallyDoIt&lt;/SPAN&gt;, it picks the object version because that’s the best it can do. If someone calls this with a string, then it still goes to the object version.&lt;/P&gt;
&lt;P&gt;Now, if you do want overload resolution to be re-executed at runtime based on the runtime types of the arguments, we can do that for you; that’s what the new “dynamic” feature does in C# 4.0. Just replace “object” with “dynamic” and when you make a call involving that object, we’ll run the overload resolution algorithm at runtime and dynamically spit code that calls the method that the compiler would have picked, had it known all the runtime types at compile time.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9803982" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/What_2700_s+The+Difference_3F00_/default.aspx">What's The Difference?</category></item><item><title>Reserved and Contextual Keywords</title><link>http://blogs.msdn.com/ericlippert/archive/2009/05/11/reserved-and-contextual-keywords.aspx</link><pubDate>Mon, 11 May 2009 18:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9593986</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>11</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9593986.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9593986</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Many programming languages, C# included, treat certain sequences of letters as “special”. &lt;/P&gt;
&lt;P&gt;Some sequences are so special that they cannot be used as identifiers. Let’s call those the “reserved keywords” and the remaining special sequences we’ll call the “contextual keywords”. They are “contextual” because the character sequence might one meaning in a context where the keyword is expected and another in a context where an identifier is expected.*&lt;/P&gt;
&lt;P&gt;The C# specification defines the following reserved keywords:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual void volatile while &lt;/SPAN&gt;
&lt;P&gt;The implementation also reserves the magic keywords &lt;SPAN class=code&gt;__arglist __makeref __reftype __refvalue&lt;/SPAN&gt; which are for obscure scenarios that I might blog about in the future. 
&lt;P&gt;Those are the keywords that we reserved in C# 1.0; no new reserved keywords have been added since. It is tempting to do so, but we always resist. Were we to add a new reserved keyword then any program that used that keyword as an identifier would break upon recompilation. Yes, you can always use a keyword as an identifier if you really want: &lt;SPAN class=code&gt;@typeof @goto = @for.@switch(@throw);&lt;/SPAN&gt; is perfectly legal, though more than a little weird. But we prefer to avoid as many breaking changes as possible.&lt;/P&gt;
&lt;P&gt;We also have a whole bunch of contextual keywords. &lt;/P&gt;
&lt;P&gt;The “preprocessor” † uses all the directives (&lt;SPAN class=code&gt;#define&lt;/SPAN&gt;, and so on) which of course were never valid identifiers in the first place. But it also uses contextual keywords &lt;SPAN class=code&gt;hidden default disable restore checksum&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;C# 1.0 had contextual keywords &lt;SPAN class=code&gt;get set value add remove&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;C# 2.0 added &lt;SPAN class=code&gt;where partial global yield alias&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;C# 3.0 added &lt;SPAN class=code&gt;from join on equals into orderby ascending descending group by select let var&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;C# 4.0 will add &lt;SPAN class=code&gt;dynamic&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;Every time we add one of these we need to carefully design the grammar so that if possible, the use of the new contextual keyword does not possibly change the meaning of an existing program which used it. &lt;/P&gt;
&lt;P&gt;For example, when defining a partial class, the &lt;SPAN class=code&gt;partial&lt;/SPAN&gt; must go immediately before the &lt;SPAN class=code&gt;class&lt;/SPAN&gt;. Since there was never a legal C# 1.0 program where &lt;SPAN class=code&gt;partial&lt;/SPAN&gt; appeared immediately before &lt;SPAN class=code&gt;class&lt;/SPAN&gt;, we knew that adding this new feature to the grammar would not possibly break any existing programs.&lt;/P&gt;
&lt;P&gt;Or, another example. Consider &lt;SPAN class=code&gt;var x = 1;&lt;/SPAN&gt; – that could have been a legal C# 2.0 program if there was a type called var with a user-defined implicit conversion from int. The semantic analyzer for declaration statements checks to see whether there is a type called var that is accessible at the declaration; if there is then the normal declaration rules are used. Only if there is not such a type can we do the analysis as an implicitly typed local declaration.&lt;/P&gt;
&lt;P&gt;One might wonder why on earth we added five contextual keywords to C# 1.0, when there was no chance of breaking backwards compatibility. Why not just make &lt;SPAN class=code&gt;get set value add remove&lt;/SPAN&gt; into “real” keywords?&lt;/P&gt;
&lt;P&gt;Because we could easily get away with making them contextual keywords, and it seemed likely that real people would want to name variables or methods things like get, set, value, add or remove. So we left them unreserved as a courtesy. &lt;/P&gt;
&lt;P&gt;Those were easy to make contextual, unlike, say, &lt;SPAN class=code&gt;return&lt;/SPAN&gt;. That’s a lot harder to make a contextual keyword because then &lt;SPAN class=code&gt;return (10);&lt;/SPAN&gt; would be ambiguous; is that calling the method named “return” or returning ten? So we didn’t make any of the other reserved keywords into contextual keywords.&lt;/P&gt;
&lt;P&gt;*******&lt;/P&gt;
&lt;P&gt;(*) An unfortunate consequence of this definition is that &lt;SPAN class=code&gt;using&lt;/SPAN&gt; is said to be a reserved keyword even though its meaning depends on its context; whether the &lt;SPAN class=code&gt;using&lt;/SPAN&gt; begins a directive or a statement determines its meaning.&lt;/P&gt;
&lt;P&gt;(†) An unfortunate name, since “preprocessing” is not done before regular language processing. In C#, the so-called “preprocessing” happens during lexical analysis.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9593986" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Breaking+Changes/default.aspx">Breaking Changes</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/keywords/default.aspx">keywords</category></item><item><title>Zip Me Up</title><link>http://blogs.msdn.com/ericlippert/archive/2009/05/07/zip-me-up.aspx</link><pubDate>Thu, 07 May 2009 17:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9586887</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>30</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9586887.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9586887</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Suppose you’ve got a sequence of Foos and you want to project from that a sequences of Bars. That’s straightforward using LINQ:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IEnumerable&amp;lt;Bars&amp;gt; bars = from foo in foos select MakeBar(foo);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;or, without the query sugar:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IEnumerable&amp;lt;Bars&amp;gt; bars = foos.Select(foo=&amp;gt;MakeBar(foo));&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;But what if you have two sequences that you want to project from? Say you’ve got two sequences of doubles that are the same length, and you want to project a sequences of points.&lt;/P&gt;
&lt;P&gt;The operation of “project from two sequences of the same length” is called a “zip join”, because its like doing up a zipper – you need each member of the left sequence to correspond to a member of the right sequence. In the version of the base class library that will ship with C# 4.0, we’ll be adding a Zip sequence operator to the standard extension methods.&lt;/P&gt;
&lt;P&gt;The code to do so is pretty trivial; if you happen to need this in C# 3.0, I’ve put the source code below.&lt;/P&gt;
&lt;P&gt;We &lt;EM&gt;considered&lt;/EM&gt; adding a query syntax for zip joins. Something like&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;from foo in foos, bar in bars select MakeBlah(foo, bar)&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;or&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;from (foo, bar) in (foos, bars) select MakeBlah(foo, bar)&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;or some such thing, which would be syntactically transformed into &lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;foos.Zip(bars, (foo, bar)=&amp;gt;MakeBlah(foo, bar))&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;However, we decided that adding a query syntax for a relatively obscure operation that is not actually supported by most relational databases was not worth the cost of complicating the grammar and the syntactic translation rules.&lt;/P&gt;
&lt;P&gt;Here’s the source code:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public static IEnumerable&amp;lt;TResult&amp;gt; Zip&amp;lt;TFirst, TSecond, TResult&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (this IEnumerable&amp;lt;TFirst&amp;gt; first, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;TSecond&amp;gt; second, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;TFirst, TSecond, TResult&amp;gt; resultSelector) &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (first == null) throw new ArgumentNullException("first");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (second == null) throw new ArgumentNullException("second");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (resultSelector == null) throw new ArgumentNullException("resultSelector");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ZipIterator(first, second, resultSelector);&lt;BR&gt;} &lt;/P&gt;
&lt;P&gt;private static IEnumerable&amp;lt;TResult&amp;gt; ZipIterator&amp;lt;TFirst, TSecond, TResult&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (IEnumerable&amp;lt;TFirst&amp;gt; first, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;TSecond&amp;gt; second, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;TFirst, TSecond, TResult&amp;gt; resultSelector) &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (IEnumerator&amp;lt;TFirst&amp;gt; e1 = first.GetEnumerator())&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (IEnumerator&amp;lt;TSecond&amp;gt; e2 = 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; while (e1.MoveNext() &amp;amp;&amp;amp; e2.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; yield return resultSelector(e1.Current, e2.Current);&lt;BR&gt;} &lt;/P&gt;&lt;/SPAN&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9586887" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Language+Design/default.aspx">Language Design</category></item><item><title>Locks and exceptions do not mix</title><link>http://blogs.msdn.com/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx</link><pubDate>Fri, 06 Mar 2009 19:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9460149</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>38</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9460149.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9460149</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;A couple years ago I wrote a bit about how our codegen for the lock statement could sometimes lead to situations in which an unoptimized build had &lt;A href="http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx"&gt;different potential deadlocks&lt;/A&gt; than an optimized build of the same source code. This is unfortunate, so we've fixed that for C# 4.0. However, all is still not rainbows, unicorns and Obama, as we'll see.&lt;/P&gt;
&lt;P&gt;Recall that &lt;SPAN class=code&gt;lock(obj){body}&lt;/SPAN&gt; was a syntactic sugar for &lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var temp = obj;&lt;BR&gt;Monitor.Enter(temp);&lt;BR&gt;try { body }&lt;BR&gt;finally { Monitor.Exit(temp); }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The problem here is that if the compiler generates a no-op instruction between the monitor enter and the try-protected region then it is possible for the runtime to throw a thread abort exception after the monitor enter but before the try. In that scenario, the finally never runs so the lock leaks, probably eventually deadlocking the program. It would be nice if this were impossible in unoptimized and optimized builds.&lt;/P&gt;
&lt;P&gt;In C# 4.0 we've changed lock so that it now generates code as if it were&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;bool lockWasTaken = false;&lt;BR&gt;var temp = obj;&lt;BR&gt;try { Monitor.Enter(temp, ref lockWasTaken); { body } }&lt;BR&gt;finally { if (lockWasTaken) Monitor.Exit(temp); }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The problem now becomes someone else's problem; the implementation of Monitor.Enter takes on responsibility for atomically setting the flag in a manner that is immune to thread abort exceptions messing it up. &lt;/P&gt;
&lt;P&gt;So everything is good now, right?&lt;/P&gt;
&lt;P&gt;Sadly, no. It's &lt;EM&gt;consistently bad&lt;/EM&gt; now, which is better than being inconsistently bad. But there's an enormous problem with this approach. By choosing these semantics for "lock" we have made a potentially unwarranted and dangerous choice on your behalf; &lt;STRONG&gt;implicit in this codegen is the belief that a deadlocked program is the worst thing that can happen&lt;/STRONG&gt;. That's not necessarily true! &lt;STRONG&gt;Sometimes deadlocking the program is the better thing to do -- the lesser of two evils.&amp;nbsp;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;The &lt;EM&gt;purpose&lt;/EM&gt; of the lock statement is to help you protect the integrity of a mutable resource that is shared by multiple threads.&amp;nbsp;But suppose an exception is thrown halfway through a mutation of the locked resource. Our implementation of lock does not magically roll back the mutation to its pristine state, and it does not complete the mutation. Rather, control &lt;EM&gt;immediately&lt;/EM&gt; branches to the finally, releasing the lock and allowing every other thread that is patiently waiting to&amp;nbsp;&lt;EM&gt;immediately&lt;/EM&gt; view the messed-up partially mutated state! If that state has privacy, security, or human life and safety implications, the result could be very bad indeed. In that case it is &lt;EM&gt;possibly&lt;/EM&gt; better to deadlock the program and protect the messed-up resource by denying access to it entirely. But that's obviously not good either.&lt;/P&gt;
&lt;P&gt;Basically, we all have a difficult choice to make whenever doing multi-threaded programming. We can (1) automatically release locks upon exceptions, exposing inconsistent state and living with the resulting bugs (bad)&amp;nbsp;(2) maintain locks upon exceptions, deadlocking the program (arguably often worse)&amp;nbsp;or (3) carefully implement the bodies of locks that&amp;nbsp;do mutations so that in the event of an exception, the mutated resource is rolled back to a pristine state before the lock is released. (Good, but hard.)&lt;/P&gt;
&lt;P&gt;This is yet another reason why &lt;STRONG&gt;the body of a lock should do as little as possible&lt;/STRONG&gt;. Usually the rationale for having small lock bodies is to get in and get out quickly, so that anyone waiting on the lock does not have to wait long. But an even better reason is because small, simple lock bodies minimize the chance that the thing in there is going to throw an exception. It's also easier to rewrite mutating lock bodies to have rollback behaviour if they don't do very much to begin with.&lt;/P&gt;
&lt;P&gt;And of course, this is yet another reason why aborting a thread is pure evil. Try to never do so!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9460149" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>The Future Of C#, Part Five</title><link>http://blogs.msdn.com/ericlippert/archive/2008/11/07/the-future-of-c-part-five.aspx</link><pubDate>Fri, 07 Nov 2008 19:18:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9052537</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>73</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9052537.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9052537</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;When we're designing a new version of the language, something we think about a lot is whether the proposed new features "hang together". Having a consistent "theme" to a release makes it easier for us to prioritize and organize proposals, it makes it easier for our marketing and user education people to effectively communicate with customers, it's just all-around goodness.&lt;/P&gt;
&lt;P&gt;If you look at C# 2.0, it was a bit of a grab-bag. The big features were clustered around the notion of enabling rich, typesafe programming with abstract data types that represent collections of data -- and thus generic types and iterator blocks. But there was a whole lot of other stuff in there as well: implementing anonymous methods&amp;nbsp;was a major feature that doesn't fit well with this theme.&amp;nbsp;And there were other more minor features as well: partial classes, improvements to properties, and so on. &lt;/P&gt;
&lt;P&gt;With C# 3.0, the theme was very clear: &lt;STRONG&gt;language-integrated query&lt;/STRONG&gt;. Anything that did not directly support LINQ was immediately made lower priority. It is rather amazing to me that partial methods and auto-implemented properties got in at all; that they were relatively easy features to design, implement, test and document was what saved them.&lt;/P&gt;
&lt;P&gt;What then is the theme of C# 4.0?&amp;nbsp;Again, it seems like rather a grab-bag: covariance and contravariance, improved interop with dynamic languages, improved interop with legacy COM object models, named and optional parameters. It also seems like a pretty small set of new features compared to generics or query comprehensions.&lt;/P&gt;
&lt;P&gt;That was deliberate. Some feedback that we received loud and clear throught the C# 3.0 ship cycle was "&lt;EM&gt;this&lt;/EM&gt; &lt;EM&gt;is awesome, we need these language features immediately!&lt;/EM&gt;" and, somewhat contradictorily, "&lt;EM&gt;please stop fundamentally changing the way I think about programming every couple years!&lt;/EM&gt;" Rather than trying to find some way to yet again radically increase the expressiveness and power of the language, we decided to spend a cycle on making what we already have&amp;nbsp;work better with the other stuff in our programming platform infrastructure.&lt;/P&gt;
&lt;P&gt;"&lt;EM&gt;Now actually works the way you'd expect it to&lt;/EM&gt;" is not really a theme that gets people excited, but sometimes you've got to stop running forward at full speed and&amp;nbsp;take some time to fix the existing stuff that is annoying a lot of people. (When I was on the VSTO team I petitioned the C# team to please, please make ref parameters optional on calls to legacy COM object models, but they were too busy with designing LINQ; I'm&amp;nbsp;delighted that we've finally gotten that in.)&lt;/P&gt;
&lt;P&gt;We also want to make sure that we are anticipating the problems that people are about to face and mitigate them now. We know that dynamic languages and object models designed with dynamism in mind are becoming increasingly popular. Given that there will be stronger demand for statically typed C# to interoperate with them in the future, let's get dynamic programming interoperability in there proactively, rather than be reactive about it later.&lt;/P&gt;
&lt;P&gt;Looking forward, it's not clear what exactly the theme of future (hypothetical!) versions of the language will be. The expected onslaught of cheap hardware parallelism looms large in our minds, so that's a possible theme. Enabling metaprogramming is another possible theme on our minds, thought it is not at all clear how that would happen. (Make C# its own metalanguage? Extend expression trees to statement trees, declaration trees, and so on?&amp;nbsp;Open up the internals of the compiler and provide an object model that lets people generate programs directly?&amp;nbsp;It is hard to say what direction is the right one to go in here.) Fortunately, people way smarter than I am are thinking about these things.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9052537" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>The Future of C#, Part Four: Yet More Video</title><link>http://blogs.msdn.com/ericlippert/archive/2008/11/02/the-future-of-c-part-four-yet-more-video.aspx</link><pubDate>Sun, 02 Nov 2008 18:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9029269</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9029269.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9029269</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;A class="" href="http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/" mce_href="http://channel9.msdn.com/shows/Going+Deep/Inside-C-40-dynamic-type-optional-parameters-more-COM-friendly/"&gt;Mads, Chris, Sam and me on Channel Nine.&lt;/A&gt; Enjoy.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9029269" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx">Video</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx">Covariance and Contravariance</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Channel+9/default.aspx">Channel 9</category></item><item><title>The Future of C#, Part Three: On video, plus the dead-trees edition</title><link>http://blogs.msdn.com/ericlippert/archive/2008/10/29/the-future-of-c-part-three-on-video-plus-the-dead-trees-edition.aspx</link><pubDate>Wed, 29 Oct 2008 19:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9022633</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9022633.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9022633</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Amazingly enough,&lt;A href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx"&gt; it has happened &lt;EM&gt;again&lt;/EM&gt;&lt;/A&gt;. Why does this keep happening to me?&lt;/P&gt;
&lt;P&gt;Anders, Mads and Eric on C# 4.0: &lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.informit.com/podcasts/episode.aspx?e=ff719d1a-67c8-47c9-86f4-0d31f2723e6f" mce_href="http://www.informit.com/podcasts/episode.aspx?e=ff719d1a-67c8-47c9-86f4-0d31f2723e6f"&gt;C# 4.0 with Anders Hejlsberg, Mads Torgersen, and Eric Lippert - Part 1 of 2&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.informit.com/podcasts/episode.aspx?e=4b0da588-4e09-4f4a-bb8a-2c1d7d2ff1f6" mce_href="http://www.informit.com/podcasts/episode.aspx?e=4b0da588-4e09-4f4a-bb8a-2c1d7d2ff1f6"&gt;C# 4.0 with Anders Hejlsberg, Mads Torgersen, and Eric Lippert - Part 2 of 2&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Anders, Mads and Scott on the new dead-trees edition of the C# 3.0 specification:&lt;/P&gt;
&lt;P&gt;&lt;A href="http://www.informit.com/podcasts/episode.aspx?e=fa08723e-aadf-4366-a66c-7c03f7db2e52" mce_href="http://www.informit.com/podcasts/episode.aspx?e=fa08723e-aadf-4366-a66c-7c03f7db2e52"&gt;The C# Programming Language, 3rd Edition&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;Enjoy!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9022633" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx">Video</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Books/default.aspx">Books</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>The Future of C#, Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2008/10/28/the-future-of-c-part-two.aspx</link><pubDate>Tue, 28 Oct 2008 18:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9020433</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>32</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9020433.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9020433</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Well, I &lt;EM&gt;intended&lt;/EM&gt; to spend the last three weeks blogging about C# design process in anticipation of our announcements at the PDC, and then I got crazy busy at work and never managed to do so! &lt;/P&gt;
&lt;P&gt;As I'm sure you know by now, we have announced the existence and feature set of that hitherto hypothetical language C# 4.0. Of course I'll be blogging extensively about that over the next year; today though I want to pick up where I left off last time and talk about the tragedy of Object Happiness Disease.&lt;/P&gt;
&lt;P&gt;OHD is a disorder believed to be related to &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2004/02/15/the-tragedy-of-thread-happiness-disease.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2004/02/15/the-tragedy-of-thread-happiness-disease.aspx"&gt;Thread Happiness Disease&lt;/A&gt;, the belief that threads are awesome and that you should therefore&amp;nbsp;make as many as you possibly can. OHD is an even more common condition which afflicts developers at all levels of experience. Symptoms of OHD in C# developers&amp;nbsp;include:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;making utterances like "I don't like extension methods because they're not object-oriented"&lt;/LI&gt;
&lt;LI&gt;requesting that multiple class inheritance be added to the language&lt;/LI&gt;
&lt;LI&gt;writing interfaces only intended to be&amp;nbsp;implemented by one class&lt;/LI&gt;
&lt;LI&gt;designing every class&amp;nbsp;to enable&amp;nbsp;derivation, whether it needs it or not&lt;/LI&gt;
&lt;LI&gt;and so on.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In short, the Object Happy believe that object-oriented programming is a good in of itself and&amp;nbsp;that OOP principles are objectively (ha ha) good principles.&lt;/P&gt;
&lt;P&gt;I don't share these beliefs.&lt;/P&gt;
&lt;P&gt;Now, don't get me wrong. I believe that OOP is frequently useful. In fact, it is frequently the best available tool&amp;nbsp;for a great many real-world jobs. OOP works particularly well when you have:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;multi-person teams of software enginneers,&lt;/LI&gt;
&lt;LI&gt;working on solving practical problems,&lt;/LI&gt;
&lt;LI&gt;by logically&amp;nbsp;associating the problem data with the functions performed upon them,&lt;/LI&gt;
&lt;LI&gt;in a type hierarchy that sensibly models the "is a" and "can do" relationships between the various parts.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;And &lt;EM&gt;that&lt;/EM&gt; is where its goodness comes from: OOP techniques make real people more productive in solving real problems and thereby creating value. &lt;STRONG&gt;The techniques are not good in of themselves, they're good because they're practical.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Perhaps surprisingly, our goal in making C# is &lt;EM&gt;not&lt;/EM&gt; to make an object-oriented language. Our goal is&lt;STRONG&gt; to make a compelling and practical language for general-purpose application development on our platforms, and thereby&amp;nbsp;enable our customers to be successful.&lt;/STRONG&gt; Making an object-oriented language called C#&amp;nbsp;is just a means to that end, not an end&amp;nbsp;in of&amp;nbsp;itself.&lt;/P&gt;
&lt;P&gt;So, yes, the oft-heard criticism that "&lt;EM&gt;extension methods are not object-oriented&lt;/EM&gt;" is entirely &lt;EM&gt;correct&lt;/EM&gt;, but also rather &lt;EM&gt;irrelevant&lt;/EM&gt;. Extension methods certainly are not object-oriented. They put the code that manipulates the data far away from the code that declares the data, they cannot break encapsulation and talk to the private state of the&amp;nbsp;objects they appear to be methods on,&amp;nbsp;they do not play well with inheritance, and so on. They're procedural programming in a convenient object-oriented dress.&lt;/P&gt;
&lt;P&gt;They're also &lt;EM&gt;incredibly convenient&lt;/EM&gt; and &lt;EM&gt;make LINQ possible&lt;/EM&gt;, which is why we added them. The fact that they do not conform to some philosophical ideal of what makes an object-oriented language was not really&amp;nbsp;much of&amp;nbsp;a factor in that decision.&lt;/P&gt;
&lt;P&gt;Here's another way to think about it. &lt;/P&gt;
&lt;P&gt;I had a discussion with Jim Miller a while back about the meaning of the term "functional language" in the context of Scheme. To paraphrase somewhat, Jim's position was along the lines that a "functional language" is one in which the design of the language makes it &lt;STRONG&gt;easy to program in a functional style&lt;/STRONG&gt; and &lt;STRONG&gt;difficult (or impossible!)&amp;nbsp;to program in a non-functional style&lt;/STRONG&gt;. For example, Scheme does allow mutation of shared state -- a very non-functional-style feature --&amp;nbsp;but the convention in Scheme is to call attention to the fact that you are doing so by marking mutating functions with a "!". It is &lt;EM&gt;possible&lt;/EM&gt; to program in an object-oriented style in Scheme, but the language resists you at every turn.&lt;/P&gt;
&lt;P&gt;I certainly&amp;nbsp;see the merits of Jim's position, but I take a weaker stance. When I say "functional language", I mean a language in which it is &lt;STRONG&gt;possible without undue difficulty to program in a functional style&lt;/STRONG&gt;. I do not&amp;nbsp;require the language to &lt;EM&gt;work against you&lt;/EM&gt; if you try to program in a non-functional style in it.&amp;nbsp;For example, I would call JScript a functional language. It is certainly possible to program in a non-functional style in JScript, but you can also treat JScript as Scheme with a slightly goofy syntax if you really want to. &lt;/P&gt;
&lt;P&gt;I think about "object-oriented language" the same way; C# is an object-oriented language not because every feature of the language strictly adheres to OO philosophy. Rather, because as a practical matter it is &lt;EM&gt;possible&lt;/EM&gt; to program in an OO style in C# if that's what you want. Adding features that enable other styles of programming does not make C# less of an OO language.&lt;/P&gt;
&lt;P&gt;Next time, I'll talk a bit about the "theme" of C# 4.0 and how that influenced the design process. (And if you absolutely positively cannot wait to hear about some of the new language feature in detail, try my colleague &lt;A class="" href="http://blogs.msdn.com/cburrows/archive/2008/10/27/c-dynamic.aspx" mce_href="http://blogs.msdn.com/cburrows/archive/2008/10/27/c-dynamic.aspx"&gt;Chris Burrows' blog&lt;/A&gt;.)&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9020433" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Software+development+methodology/default.aspx">Software development methodology</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>The Future of C#, Part One</title><link>http://blogs.msdn.com/ericlippert/archive/2008/10/08/the-future-of-c-part-one.aspx</link><pubDate>Wed, 08 Oct 2008 18:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8985678</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>29</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8985678.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8985678</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;An attentive reader pointed me at this &lt;A class="" href="http://www.codeproject.com/Lounge.aspx?fid=1159&amp;amp;select=2747603&amp;amp;tid=2747603#xx2747603xx" mce_href="http://www.codeproject.com/Lounge.aspx?fid=1159&amp;amp;select=2747603&amp;amp;tid=2747603#xx2747603xx"&gt;long&amp;nbsp;thread&lt;/A&gt; on a third-party forum where some people are musing about possible future features of C#. There is far, far more here than I possibly have time to respond to in any kind of detail.&lt;/P&gt;
&lt;P&gt;Also,&lt;STRONG&gt;&amp;nbsp;I am not going to spill the beans&lt;/STRONG&gt;. &lt;A class="" href="http://channel9.msdn.com/pdc2008/TL16/" mce_href="http://channel9.msdn.com/pdc2008/TL16/"&gt;Anders is giving a talk at the PDC&lt;/A&gt; at the end of the month. His talk is titled "The Future of C#" and I'm not going to steal Anders' thunder (or give our marketing department conniptions) by giving specific details at this time. &lt;/P&gt;
&lt;P&gt;Of course, I note also that we have not announced that there even will be a&amp;nbsp;language called C# 4. We have not announced that there will be new versions of Visual Studio or the CLR either. But we also know that you people who read blogs about programming languages are not idiots. I posted a link to a &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx"&gt;video&lt;/A&gt; a while back where Charles interviews the C# design team; the fact that there is a design team is evidence that we're designing &lt;EM&gt;something&lt;/EM&gt;. I've been posting about adding more&amp;nbsp;&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx"&gt;covariance and contravariance&lt;/A&gt; to the type system, Charlie has been collecting comments about what &lt;A class="" href="http://blogs.msdn.com/charlie/archive/2008/01/25/future-focus.aspx" mce_href="http://blogs.msdn.com/charlie/archive/2008/01/25/future-focus.aspx"&gt;kinds of interactions people would like to see between C# and dynamic languages&lt;/A&gt;. Clearly we're up to something here, and it is not hard to figure out the broad outlines.&lt;/P&gt;
&lt;P&gt;This puts me in a bit of a tight spot -- I want to respond to all these great ideas, I want to inform the community about our plans and get feedback early, but at the same time I want to make sure that we don't overpromise and underdeliver, and I want to ensure that we provide information that is fully-baked and professionally presented.&lt;/P&gt;
&lt;P&gt;Therefore, I want to&amp;nbsp;talk about these&amp;nbsp;ideas &lt;EM&gt;in the context of the design process we go through here&lt;/EM&gt;, rather than in the context of specific&amp;nbsp;implementation decisions of specific features. &lt;/P&gt;
&lt;P&gt;I made a new friend at a birthday party I attended the other day. We got to making small talk about our jobs. I mentioned that I designed programming languages as part of my job. Now, let me tell you, when I say that at a party&amp;nbsp;I get one of&amp;nbsp;three responses: (1) that's really cool, (2)&amp;nbsp;excuse me, I need to refill this drink, or (3) a puzzled look, followed by "you mean, someone actually &lt;EM&gt;designs&lt;/EM&gt; programming languages? I thought they just, you know, sprang into existence... somehow." I informed my new friend that no, in fact there is a huge amount of design that goes into a language -- six hours a week of meetings for almost&amp;nbsp;ten years, in fact, for C# alone.&lt;/P&gt;
&lt;P&gt;I've already linked several times to &lt;A class="" href="http://blogs.msdn.com/ericgu/archive/2004/01/12/57985.aspx" mce_href="http://blogs.msdn.com/ericgu/archive/2004/01/12/57985.aspx"&gt;Eric Gunnerson's great post on the C# design process&lt;/A&gt;. The two most important points in Eric's post are: (1) &lt;STRONG&gt;this is not a subtractive process&lt;/STRONG&gt;; we don't start with C++ or Java or Haskell and then decide whether to leave some feature of them out. And (2) &lt;STRONG&gt;just&lt;/STRONG&gt; &lt;STRONG&gt;being a good feature is not enough&lt;/STRONG&gt;. Features have to be so compelling that they are worth the enormous dollar costs of designing, implementing, testing, documenting and shipping the feature. They have to be worth the cost of complicating the language and making it more difficult to design other features in the future.&lt;/P&gt;
&lt;P&gt;After we finished the last-minute minor redesigns of various parts of C# 3.0, we made a list of every feature we could think of that could possibly go into a future version of C#. We spent many, many hours going through each feature on that list, trying to "bucket" it. Each feature got put into a unique bucket. The buckets were labelled:&lt;/P&gt;
&lt;P&gt;Pri 1: Must have in the next version&lt;BR&gt;Pri 2: Should have in the next version&lt;BR&gt;Pri 3: Nice to have in the next version&lt;BR&gt;Pri 4: Likely requires deep study for many years before we can do it&lt;BR&gt;Pri 5: Bad idea&lt;/P&gt;
&lt;P&gt;Obviously we immediately stopped considering the fours and fives in the context of the next version. We then added up the costs of the features in the first three buckets, compared them against the design, implementation, testing and documenting resources we had available. The costs were massively higher than the resources available, so we&amp;nbsp;cut everything in bucket 2 and 3, and about half of what was in bucket 1. Turns out that some of those "must haves" were actually "should haves".&lt;/P&gt;
&lt;P&gt;Understanding this bucketing process will help when I talk about some of the features suggested in that long forum topic. Many of the features suggested were perfectly good, but fell into bucket 3. They didn't make up the 100 point deficit, they just weren't compelling enough.&lt;/P&gt;
&lt;P&gt;Next time, I think I'll talk a bit about the design process in the context of OOP.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8985678" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category></item><item><title>A Face Made For Email, Part Four</title><link>http://blogs.msdn.com/ericlippert/archive/2008/07/14/a-face-made-for-email-part-four.aspx</link><pubDate>Mon, 14 Jul 2008 20:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8731821</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8731821.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8731821</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Good heavens, &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx"&gt;this&lt;/A&gt; just keeps on happening to me.&lt;/P&gt;
&lt;P&gt;If you're interested in what we're musing about for future versions of C#, &lt;A class="" href="http://channel9.msdn.com/posts/Charles/C-40-Meet-the-Design-Team/" mce_href="http://channel9.msdn.com/posts/Charles/C-40-Meet-the-Design-Team/"&gt;check out this video&lt;/A&gt; of Anders Hejlsberg, &lt;A class="" href="http://blogs.msdn.com/scottwil/" mce_href="http://blogs.msdn.com/scottwil/"&gt;Scott Wiltamuth&lt;/A&gt;, &lt;A class="" href="http://www.panopticoncentral.net/" mce_href="http://www.panopticoncentral.net/"&gt;Paul Vick&lt;/A&gt;, &lt;A class="" href="http://blogs.msdn.com/madst" mce_href="http://blogs.msdn.com/madst"&gt;Mads Torgersen&lt;/A&gt;, &lt;A class="" href="http://blogs.msdn.com/mattwar" mce_href="http://blogs.msdn.com/mattwar"&gt;Matt Warren&lt;/A&gt;, &lt;A class="" href="http://blogs.msdn.com/hugunin/" mce_href="http://blogs.msdn.com/hugunin/"&gt;Jim Hugunin&lt;/A&gt; and, off in one corner, me.&lt;/P&gt;
&lt;P&gt;Working with this caliber of people every day is a huge part of what makes this the best job ever.&lt;/P&gt;
&lt;P&gt;&lt;A href="http://channel9.msdn.com/posts/Charles/C-40-Meet-the-Design-Team/"&gt;http://channel9.msdn.com/posts/Charles/C-40-Meet-the-Design-Team/&lt;/A&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8731821" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Video/default.aspx">Video</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Channel+9/default.aspx">Channel 9</category></item></channel></rss>