<?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 : Covariance and Contravariance</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx</link><description>Tags: Covariance and Contravariance</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>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 is covariance of value-typed arrays inconsistent?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/09/24/why-is-covariance-of-value-typed-arrays-inconsistent.aspx</link><pubDate>Thu, 24 Sep 2009 16:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895929</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9895929.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9895929</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Another&amp;nbsp;interesting &lt;A class="" href="http://stackoverflow.com/questions/1178973/why-does-my-c-array-lose-type-sign-information-when-cast-to-object/1179094#1179094" mce_href="http://stackoverflow.com/questions/1178973/why-does-my-c-array-lose-type-sign-information-when-cast-to-object/1179094#1179094"&gt;question from StackOverflow&lt;/A&gt;:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;uint[] foo = new uint[10];&lt;BR&gt;object bar = foo;&lt;BR&gt;Console.WriteLine("{0} {1} {2} {3}",&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp; foo is uint[],&amp;nbsp;// True&lt;BR&gt;&amp;nbsp; foo is int[],&amp;nbsp;&amp;nbsp;// False&lt;BR&gt;&amp;nbsp; bar is uint[],&amp;nbsp;// True&lt;BR&gt;&amp;nbsp; bar is int[]);&amp;nbsp;// True&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;What the heck is going on here?&lt;/P&gt;
&lt;P&gt;This program fragment illustrates an interesting and unfortunate inconsistency between the CLI type system and the C# type system.&lt;/P&gt;
&lt;P&gt;The CLI has the concept of "assignment compatibility". If a value x of known data type S is "assignment compatible" with a particular storage location y of known data type T, then you can store x in y. If not, then doing so is not verifiable code and the verifier will disallow it.&lt;/P&gt;
&lt;P&gt;The CLI type system says, for instance, that subtypes of reference type are assignment compatible with supertypes of reference type. If you have a string, you can store it in a variable of type object, because both are reference types and string is a subtype of object. But the opposite is not true; supertypes are not assignment compatible with subtypes. You can't stick something only known to be object into a variable of type string without first casting it.&lt;/P&gt;
&lt;P&gt;Basically "assignment compatible" means "&lt;EM&gt;it makes sense to stick these exact bits into this variable&lt;/EM&gt;". The assignment from source value to target variable has to be "&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx"&gt;representation preserving&lt;/A&gt;". &lt;A href="http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx"&gt;&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;One of the rules of the CLI is "&lt;EM&gt;if X is assignment compatible with Y then X[] is assignment compatible with Y[]&lt;/EM&gt;". &lt;/P&gt;
&lt;P&gt;That is, arrays are covariant with respect to assignment compatibility. As I've discussed already, &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx"&gt;this is actually a broken kind of covariance&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;That is &lt;EM&gt;not&lt;/EM&gt; a rule of C#. C#'s array covariance rule is "&lt;EM&gt;if X is a &lt;STRONG&gt;reference type&lt;/STRONG&gt; implicitly convertible to &lt;STRONG&gt;reference type&lt;/STRONG&gt; Y then X[] is implicitly convertible to Y[]&lt;/EM&gt;". That is a subtly different rule!&lt;/P&gt;
&lt;P&gt;In the CLI, uint and int are assignment compatible; therefore uint[] and int[] are too. But in C#, the conversion between int and uint is &lt;EM&gt;explicit&lt;/EM&gt;, not &lt;EM&gt;implicit&lt;/EM&gt;, and these are &lt;EM&gt;value types&lt;/EM&gt;, not &lt;EM&gt;reference types&lt;/EM&gt;. So in C# it is &lt;EM&gt;not&lt;/EM&gt; legal to convert an int[] to a uint[]. But it &lt;EM&gt;is&lt;/EM&gt; legal in the CLI. So now we are faced with a choice.&lt;/P&gt;
&lt;P&gt;1) Implement "is" so that when the compiler cannot determine the answer statically, it actually calls a method which checks all the C# rules for identity-preserving convertibility. This is slow, and 99.9% of the time matches what the CLR rules are. But we take the performance hit so as to be 100% compliant with the rules of C#.&lt;/P&gt;
&lt;P&gt;2) Implement "is" so that when the compiler cannot determine the answer statically, it does the incredibly fast CLR assignment compatibility check, and live with the fact that this says that a uint[] is an int[], even though that would not actually be legal in C#.&lt;/P&gt;
&lt;P&gt;We chose the latter. It is unfortunate that C# and the CLI specifications disagree on this minor point but we are willing to live with the inconsistency.&lt;/P&gt;
&lt;P&gt;So what's going on here is that in the "foo" cases, the compiler can determine statically what the answer is going to be according to the rules of C#, and generates code to produce "True" and "False". But in the "bar" case, the compiler no longer knows what exact type is in bar, so it generates code to make the CLR answer the question, and the CLR gives a different opinion.&lt;BR&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=9895929" 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/Arrays/default.aspx">Arrays</category></item><item><title>Why do ref and out parameters not allow type variation?</title><link>http://blogs.msdn.com/ericlippert/archive/2009/09/21/why-do-ref-and-out-parameters-not-allow-type-variation.aspx</link><pubDate>Mon, 21 Sep 2009 16:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9895925</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>16</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9895925.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9895925</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Here's a &lt;A class="" href="http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302" mce_href="http://stackoverflow.com/questions/1207144/c-why-doesnt-ref-and-out-support-polymorphism/1207302#1207302"&gt;good question from StackOverflow&lt;/A&gt;:&lt;/P&gt;
&lt;P&gt;If you have a method that takes an "X" then you have to pass an expression of type X &lt;STRONG&gt;or something convertible to X&lt;/STRONG&gt;. Say, an expression of a type derived from X. But if you have a method that takes a "ref X", you have to pass a ref to a variable of type X, period. Why is that? Why not allow the type to vary, as we do with non-ref calls?&lt;/P&gt;
&lt;P&gt;Let's suppose you have classes Animal, Mammal, Reptile, Giraffe, Turtle and Tiger, with the obvious subclassing relationships.&lt;/P&gt;
&lt;P&gt;Now suppose you have a method void M(ref Mammal m). M can both read and write m. Can you pass a variable of type Animal to M? No. That would not be safe. That variable could contain a Turtle, but M will assume that it contains only Mammals. A Turtle is not a Mammal.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusion 1&lt;/STRONG&gt;: Ref parameters cannot be made "bigger". (There are more animals than mammals, so the variable is getting "bigger" because it can contain more things.)&lt;/P&gt;
&lt;P&gt;Can you pass a variable of type Giraffe to M? No. M can write to m, and M might want to write a Tiger into m. Now you've put a Tiger into a variable which is actually of type Giraffe.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusion 2&lt;/STRONG&gt;: Ref parameters cannot be made "smaller".&lt;/P&gt;
&lt;P&gt;Now consider N(out Mammal n).&lt;/P&gt;
&lt;P&gt;Can you pass a variable of type Giraffe to N? No. As with our previous example, N can write to n, and N might want to write a Tiger. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusion 3&lt;/STRONG&gt;: Out parameters cannot be made "smaller".&lt;/P&gt;
&lt;P&gt;Can you pass a variable of type Animal to N?&lt;/P&gt;
&lt;P&gt;Hmm.&lt;/P&gt;
&lt;P&gt;Well, why not? N cannot read from n, it can only write to it, right? You write a Tiger to a variable of type Animal and you're all set, right?&lt;/P&gt;
&lt;P&gt;Wrong. The rule is not "N can only write to n". The rules are, briefly: &lt;/P&gt;
&lt;P&gt;1) N has to write to n before N returns normally. (If N throws, all bets are off.)&lt;BR&gt;2) N has to write something to n &lt;EM&gt;before it reads something from n&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;That permits this sequence of events:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Declare a field x of type Animal. &lt;/LI&gt;
&lt;LI&gt;Pass x as an out parameter to N. &lt;/LI&gt;
&lt;LI&gt;N writes a Tiger into n, which is an alias for x. &lt;/LI&gt;
&lt;LI&gt;On another thread, someone writes a Turtle into x. &lt;/LI&gt;
&lt;LI&gt;N attempts to read the contents of n, and discovers a Turtle in what it thinks is a variable of type Mammal.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That scenario -- using multithreading to write into a variable that has been aliased&amp;nbsp;--&amp;nbsp;is awful and you should never do it, but it is possible.&lt;/P&gt;
&lt;P&gt;UPDATE: Commenter Pavel Minaev correctly notes that there is no need for multithreading to cause mayhem. We could replace that fourth step with&lt;/P&gt;
&lt;LI&gt;N makes a call to a method which directly or indirectly causes some code to write a Turtle into x.&lt;/LI&gt;
&lt;P&gt;Regardless of how the variable's contents&amp;nbsp;might get altered, clearly we want to make the type system violation illegal. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Conclusion 4&lt;/STRONG&gt;: Out parameters cannot be made "larger".&lt;/P&gt;
&lt;P&gt;There is another argument which supports this conclusion:&amp;nbsp;"out" and "ref" are actually exactly the same&amp;nbsp;behind the scenes.&amp;nbsp;The CLR only supports "ref"; "out" is just "ref" where the compiler enforces slightly different rules&amp;nbsp;regarding when the variable in question is known to have been definitely assigned. That's why it is illegal to make method overloads that differ solely in out/ref-ness; the CLR cannot tell them apart! Therefore the rules for type safety for out have to be the same as for ref.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Final conclusion&lt;/STRONG&gt;: Neither ref nor out parameters may vary&amp;nbsp;in type at the call site. To do otherwise is to break verifiable type safety.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9895925" 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/Conversions/default.aspx">Conversions</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/type+safety/default.aspx">type safety</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/reference/default.aspx">reference</category></item><item><title>The void is invariant</title><link>http://blogs.msdn.com/ericlippert/archive/2009/06/29/the-void-is-invariant.aspx</link><pubDate>Mon, 29 Jun 2009 17:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9756024</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>19</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9756024.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9756024</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;[UPDATES below]&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A while back I described &lt;A href="http://blogs.msdn.com/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx"&gt;a kind of variance that we’ve supported since C# 2.0.&lt;/A&gt; When assigning a method group to a delegate type, such that both the selected method and the delegate target agree that their return type is a reference type, then the conversion is allowed to be covariant. That is, you can say:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Giraffe GetGiraffe() { … }&lt;BR&gt;…&lt;BR&gt;Func&amp;lt;Animal&amp;gt; f = GetGiraffe;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This works logically because anyone who calls f must be able to handle any animal that comes back. The actual method claims to only return animals, and in fact, makes the stronger claim to only return giraffes. &lt;/P&gt;
&lt;P&gt;This works out in the CLR because the bits that make up a reference to an instance of Giraffe are exactly the same bits that make up a reference to that Giraffe interpreted as an instance of Animal. We can allow this magical conversion to happen because the CLR guarantees that it will all just work out without going in there and having to futz around with the bits.&lt;/P&gt;
&lt;P&gt;This is why this trick only works with reference types. A method that returns, say, a double cannot be converted via a covariant conversion to a delegate type that expects the method to return an object. Somewhere there would have to be code emitted that takes the returned double and boxes it to object; the bits of a double and the bits of a reference to an object boxing a double are completely different.&lt;/P&gt;
&lt;P&gt;But why doesn’t this trick work with void types? Here we have a method that returns some sort of success or failure code. Maybe we don’t care what it returns.&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static bool DoSomething(bool b)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; if (b) return DoTheThing();&lt;BR&gt;&amp;nbsp; else return DoTheOtherThing();&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Action&amp;lt;bool&amp;gt; action = DoSomething;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This doesn’t work. Why not? The caller of the action is not even going to &lt;EM&gt;use&lt;/EM&gt; the returned value, so it doesn’t matter one bit what it is! Shouldn’t “void” be considered &lt;EM&gt;a supertype of all possible types&lt;/EM&gt; for the purposes of covariant return type conversions from method groups to delegate types?&lt;/P&gt;
&lt;P&gt;No, and I’ll tell you why.&lt;/P&gt;
&lt;P&gt;Consider what happens when you do this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;bool x = DoSomething(true);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We spit out IL that does the following:&lt;/P&gt;
&lt;P&gt;(1) put true on the IL stack – the stack gets one deeper&lt;BR&gt;(2) call DoSomething – the argument is removed from the stack and the return value is placed on the stack.&amp;nbsp; Net, the stack stays the same size as before&lt;BR&gt;(3) stuff whatever on top of the stack into local variable x – the stack now returns to its original depth.&lt;/P&gt;
&lt;P&gt;Now consider what happens when you do this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;DoSomething(true);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We spit out IL that does the first two steps as before. But we cannot stop there! There is now a bool on the IL stack which needs to be removed. We generate a pop instruction to represent the fact that the returned bool has been discarded.&lt;/P&gt;
&lt;P&gt;Now consider what happens when you do this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;action(true);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The compiler believes that action is a void-returning method, so it does not generate a pop instruction. If we allowed you to stuff DoSomething into the action, then we would be allowing you to misalign the IL stack!&lt;/P&gt;
&lt;P&gt;But didn’t I say “&lt;A href="http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx"&gt;the stack is an implementation detail?&lt;/A&gt;” Yes, but &lt;EM&gt;that’s a different stack&lt;/EM&gt;. The CLI specification describes a “virtual machine” which passes around arguments and returned values on a stack. An implementation of the CLI is required to make something that behaves like the specified machine, but it is not required to do so in any particular manner. It is not required to use the million-bytes-per-thread stack supplied to each thread by the operating system as its implementation of the IL stack; that’s a convenient structure to use, of course, but it’s an implementation detail that it does so.&lt;/P&gt;
&lt;P&gt;(As an aside: when we implemented the script engines, we also first specified our own private stack-based virtual machine. When we implemented it, we decided to put the information about “return addresses” – that is, “what code do I run next?” on the system stack, but we put arguments and return values of script functions in a stack-shaped block of memory that we allocated on our own. This made building the JScript garbage collector easier.)&lt;/P&gt;
&lt;P&gt;In practice, the jitter uses the system stack for some things and registers for other things. Return values are actually often sent back in a register, not on the stack. But that implementation detail doesn’t help us out when deciding what the conversion rules are; we have to assume that the implementation can do no more than what the CLI specification says. Had the CLI specification said “the returned value of any function is passed back in a ‘virtual register’” rather than having it pushed onto the stack, then we could have made void-returning delegates compatible with functions that returned anything. You can always just ignore the value in the register. But that’s not what the CLI specified, so that’s not what we can do. &lt;/P&gt;
&lt;P&gt;[UPDATE]&lt;/P&gt;
&lt;P&gt;A number of people have asked in the comments why we do not simply generate a helper method that does what you want. That is, when you say&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Action&amp;lt;bool&amp;gt; action = DoSomething;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;realize that as&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static&amp;nbsp;void DoSomethingHelper(bool b)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; bool result = DoSomething(b); // result is ignored&lt;BR&gt;}&lt;BR&gt;...&lt;BR&gt;Action&amp;lt;bool&amp;gt; action = DoSomethingHelper;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We could do that. But where would you like the line to be drawn? Should you be able to assign a&amp;nbsp;reference to a method that returns an int to a Func&amp;lt;Nullable&amp;lt;int&amp;gt;&amp;gt;? We could spit a helper method that converts the int to a nullable int.&amp;nbsp;What about Func&amp;lt;double&amp;gt;? We could spit a helper method that converts the int to a double. What about Func&amp;lt;object&amp;gt;? We could spit a helper method that boxes the int, unexpectedly allocating memory off the heap every time you call it. What about a Func&amp;lt;Foo&amp;gt; where there is a user-defined implicit conversion from int to Foo?&lt;/P&gt;
&lt;P&gt;We could be spitting arbitrarily complex fixer-upper methods that would seamlessly "do what you meant to say", and we have to stop somewhere.&amp;nbsp;The exact semantics of what we&amp;nbsp;do and do not&amp;nbsp;fix up would have to be designed, specified, implemented, tested, documented, shipped to customers and maintained forever. Those are costs. Plus, &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/08/31/future-breaking-changes-part-two.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/08/31/future-breaking-changes-part-two.aspx"&gt;every time we add a new conversion rule to the language we add breaking changes&lt;/A&gt;. The costs of those breaking changes to our customers have to be factored in.&lt;/P&gt;
&lt;P&gt;But more fundamentally, one of the design principles of C# is "if &lt;STRONG&gt;you say something wrong then &lt;EM&gt;we tell you&lt;/EM&gt; rather than trying &lt;EM&gt;to guess what you meant&lt;/EM&gt;&lt;/STRONG&gt;". JScript is deliberately a "muddle on through and do the best you can" language; C# is not. If what you want to do is make a delegate to a helper method then you express that intention by going right ahead and making that method.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9756024" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</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/Breaking+Changes/default.aspx">Breaking Changes</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/Conversions/default.aspx">Conversions</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/Memory+Management/default.aspx">Memory Management</category></item><item><title>Representation and Identity</title><link>http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx</link><pubDate>Thu, 19 Mar 2009 16:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9488368</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>23</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9488368.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9488368</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I get a fair number of questions about the C# cast operator. The most frequent question I get is:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;short sss = 123;&lt;BR&gt;object ooo = sss;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Box the short.&lt;BR&gt;int iii = (int) sss;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Perfectly legal.&lt;BR&gt;int jjj = (int) (short) ooo; // Perfectly legal&lt;BR&gt;int kkk = (int) ooo;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Invalid cast exception?! Why?&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Why? Because a boxed T can only be unboxed to T. (*) Once it is unboxed, it’s just a value that can be cast as usual, so the double cast works just fine. &lt;/P&gt;
&lt;P&gt;Many people find this restriction grating; they expect to be able to cast a boxed thing to &lt;EM&gt;anything&lt;/EM&gt; that the unboxed thing could have been cast to. There are ways to do that, as we’ll see, but there are good reasons why the cast operator does what it does.&lt;/P&gt;
&lt;P&gt;To understand why this design works this way it’s necessary to first wrap your head around the contradiction that is the cast operator. There are two (¤) basic usages of the cast operator in C#:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;My code has an expression of type B, but I happen to have more information than the compiler does. I claim to know for certain that at runtime, &lt;STRONG&gt;this object of type B will actually always be of derived type D&lt;/STRONG&gt;. I will inform the compiler of this claim by inserting a cast to D on the expression. Since the compiler probably cannot verify my claim, the compiler might ensure its veracity by inserting a run-time check at the point where I make the claim. If my claim turns out to be inaccurate, the CLR will throw an exception.&lt;BR&gt;
&lt;LI&gt;I have an expression of some type T which &lt;STRONG&gt;I know for certain is not of type U&lt;/STRONG&gt;. However, I have a well-known way of associating some or all values of T with an “equivalent” value of U. I will instruct the compiler to generate code that implements this operation by inserting a cast to U. (And if at runtime there turns out to be no equivalent value of U for the particular T I’ve got, again we throw an exception.)&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The attentive reader will have noticed that these are &lt;EM&gt;opposites&lt;/EM&gt;. A neat trick, to have an operator which means two contradictory things, don’t you think?&lt;/P&gt;
&lt;P&gt;This dichotomy motivates yet another classification scheme for conversions (†).&amp;nbsp; We can divide conversions into &lt;STRONG&gt;representation-preserving conversions&lt;/STRONG&gt; (B to D) and &lt;STRONG&gt;representation-changing conversions&lt;/STRONG&gt; (T to U). (‡) We can think of representation-preserving conversions on reference types as those conversions which &lt;EM&gt;preserve the identity of the object&lt;/EM&gt;. When you cast a B to a D, you’re not doing anything to the existing object; you’re merely &lt;EM&gt;verifying&lt;/EM&gt; that it is actually the type you say it is, and moving on. The identity of the object and&amp;nbsp;the bits which represent the&amp;nbsp;reference&amp;nbsp;stay the same. But when you cast an int to a double, the resulting bits are very different. &lt;/P&gt;
&lt;P&gt;All the built-in reference conversions are identity-preserving (£). Obviously trivial “conversions” such as converting from int to int are also representation-preserving conversions. All user-defined conversions (§) and non-trivial value type conversions (such as converting from int to double) are representation-changing conversions. Boxing and unboxing conversions are all representation-changing conversions.&lt;/P&gt;
&lt;P&gt;The representation-preserving conversions that are known to never fail often result in no codegen at all (₪). If a representation-preserving conversion could fail then a castclass instruction is emitted, which does a runtime check and throws if the check fails. &lt;/P&gt;
&lt;P&gt;But each representation-changing conversion is handled in its own special way. User-defined conversions are resolved using a special version of the overload resolution algorithm, and generated as a call to the appropriate static method. Boxing and unboxing conversions are generated as box and unbox instructions. All the other built-in conversions (int to double, and so on) are generated as &lt;STRONG&gt;custom sequences of instructions&lt;/STRONG&gt; that do the right conversion.&lt;/P&gt;
&lt;P&gt;So now that you know that, consider what the compiler would have to do to make this work the way some people expect:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;int kkk = (int) ooo; &lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;All that the compiler knows is that ooo is of type object. It could be &lt;EM&gt;anything&lt;/EM&gt;. Suppose it is a boxed int – then the compiler should generate an unboxing instruction. Suppose it is a boxed short. Then the compiler should unbox the short and then generate the custom sequence of instructions that convert a short to an&amp;nbsp;int. Suppose it is a boxed double – same thing, but different instructions. And so on, for all the built-in conversions that go to integer.&lt;/P&gt;
&lt;P&gt;This would be a huge amount of code to generate, and it would be very slow. The code is of course so large that you would want to put it in its own method and just generate a call to it. Rather than do that by default, and always generate code that is slow, large and fragile, instead we’ve decided that unboxing can only unbox to the exact type. If you want to call the slow method that does all that goo, it’s available – you can always call Convert.ToInt32, which does all that analysis at runtime for you. We give you the choice between “fast and precise” or “slow and lax”, and &lt;EM&gt;the sensible default is the former&lt;/EM&gt;. If you want the latter then call the method.&lt;/P&gt;
&lt;P&gt;That’s just the built-in conversions. Let’s continue imagining what would have to happen if we wanted &lt;EM&gt;all possible conversions&lt;/EM&gt; to int to just work out correctly at runtime, instead of just bailing out early if the boxed thing is not an int.&lt;/P&gt;
&lt;P&gt;Suppose the object is a Foo where there is a user-defined conversion from Foo (or one of its base classes) to int (or a type implicitly convertible to int, like, say, Nullable&amp;lt;int&amp;gt;). Then the compiler would need to generate a call to that conversion method, just as it would if the type had been known at compile time, and then possibly also generate the conversion from the return type of the method to int.&lt;/P&gt;
&lt;P&gt;Remember, there could be arbitrarily many such conversion methods on arbitrarily many types. The type Foo and its conversion method&amp;nbsp;might not even be defined in the assembly currently&amp;nbsp;being compiled or any assembly referenced. Therefore the compiler would have to generate code to interrogate Foo at runtime, do the overload resolution analysis, and then dynamically spit the code to do the call.&lt;/P&gt;
&lt;P&gt;Which is exactly what the compiler does in C# 4.0 if the argument to the cast is of type “dynamic” instead of object. &lt;EM&gt;The compiler actually generates code which starts a mini version of the compiler up again at runtime, does all that analysis, and spits fresh code&lt;/EM&gt;. This is not &lt;EM&gt;fast&lt;/EM&gt;, but it is &lt;EM&gt;accurate&lt;/EM&gt;, if that’s what you really need. (And the spit code is then cached so that the next time this call site is hit, it is much faster.)&lt;/P&gt;
&lt;P&gt;I don’t think people &lt;EM&gt;really&lt;/EM&gt; expect the compiler to start up again at runtime every time they cast an object to int; I think they just haven’t thought through carefully exactly how much analysis solving the problem would take. Rather a lot, it turns out.&lt;/P&gt;
&lt;P&gt;*************&lt;/P&gt;
&lt;P&gt;(*) Or Nullable&amp;lt;T&amp;gt;.&lt;/P&gt;
&lt;P&gt;(¤) There are others that are not germane to this discussion. For example, a third usage is “Everyone knows that this D is also of base type B; I want the compiler to treat this expression of type D as a B for overload resolution purposes.” That would clearly be an identity-preserving conversion.&lt;/P&gt;
&lt;P&gt;(†) There are many ways to classify conversions; we already divide conversions into implicit/explicit, built-in/user-defined, and so on. For the purposes of this discussion we’ll gloss over the details of those other classifications.&lt;/P&gt;
&lt;P&gt;(‡) I’m glossing over here that certain conversions that the C# compiler thinks of as representation-changing are actually seen by the CLR verifier as representation-preserving. For example, the conversion from int to uint is seen by the CLR as representation-preserving because the 32 bits of a signed integer can be reinterpreted as an unsigned integer without changing the bits. These cases can be subtle and complex, and often have an impact on covariance-related issues; see next footnote.&lt;/P&gt;
&lt;P&gt;I’m also ignoring conversions involving generic type parameters which are not known at compile time to be reference or value types. There are special rules for classifying those which would be major digressions to get into.&lt;/P&gt;
&lt;P&gt;(£) This is why covariant and contravariant conversions of interface and delegate types require that all varying type arguments be of reference types. &lt;STRONG&gt;To ensure that a variant reference conversion is always identity-preserving, all of the conversions involving type arguments must also be identity-preserving.&lt;/STRONG&gt; The easiest way to ensure that all the non-trivial conversions on type arguments are identity-preserving is to restrict them to be reference conversions.&lt;/P&gt;
&lt;P&gt;(§) The rules of C# prohibit all user-defined conversions that could possibly be identity-preserving coercions. More generally, all user-defined conversions that could possibly be any "standard" conversion are illegal.&lt;/P&gt;
&lt;P&gt;(₪) Again, I’m ignoring irksome&amp;nbsp;generic issues here. There are situations where humans can prove mathematically that two generic type parameters must be identical at runtime, but the verifier is not smart enough to make those same deductions and requires the compiler to emit type checks.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9488368" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Performance/default.aspx">Performance</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/Code+Generation/default.aspx">Code Generation</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Conversions/default.aspx">Conversions</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/Language+Design/default.aspx">Language Design</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/cast+operator/default.aspx">cast operator</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>Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx</link><pubDate>Wed, 07 May 2008 16:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8461025</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>20</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8461025.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8461025</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P mce_keep="true"&gt;UPDATE: Andrew Kennedy, author of the paper I reference below, was good enough to point out some corrections and omissions, which I have addressed. Thanks Andrew!&lt;/P&gt;
&lt;P&gt;As I've discussed at length in this space, we are considering adding &lt;A 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; on delegate and interface types parameterized with reference types to a hypothetical future version of C#. (See my earlier articles in this series for an explanation of the proposed feature.)&lt;/P&gt;
&lt;P&gt;Variance is highly useful in mainstream cases, but exposes a really irksome problem in certain bizarre corner cases. Here's just one example.&lt;/P&gt;
&lt;P&gt;Consider a "normal" interface contravariant in its sole generic type parameter, and a "crazy" invariant interface which extends the normal interface in a strange way:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IN&amp;lt;in U&amp;gt; {}&lt;BR&gt;public interface IC&amp;lt;X&amp;gt; : IN&amp;lt;IN&amp;lt;IC&amp;lt;IC&amp;lt;X&amp;gt;&amp;gt;&amp;gt;&amp;gt; {}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This is a bit weird, but certainly legal. &lt;/P&gt;
&lt;P&gt;Before I go on, I want to digress and talk a bit about why this is legal. Most people when they first see such a beast immediately say "but an interface cannot inherit from itself, that's an illegal circularity in the inheritance chain!"&lt;/P&gt;
&lt;P&gt;First off, no, that is not correct. Nowhere does the C# specification make this kind of inheritance illegal, and in fact, a weak form of it must be legal. You want to be able to say:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface INumber&amp;lt;X&amp;gt; : IComparable&amp;lt;INumber&amp;lt;X&amp;gt;&amp;gt; { ... }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;that is, you want to be able to express that one of the guarantees of the &lt;SPAN class=code&gt;INumber&amp;lt;X&amp;gt;&lt;/SPAN&gt; contract is that you can always compare one number with another one. Therefore, it must be legal to use a type's name in a type argument of a generic base type.&lt;/P&gt;
&lt;P&gt;However, all is not rosy. This particularly gross kind of inheritance that I give as an example is in fact illegal in the CLR, even though it is not illegal&amp;nbsp;in C#. This means that it is possible to have the C# compiler generate an interface&amp;nbsp;type which then cannot be loaded by the CLR. This unfortunate mismatch is troubling, and I hope in a future version of C# to make the type definition rules of C# as strict or stricter than those of the CLR. Until then, if it hurts when you do that, don't do it.&lt;/P&gt;
&lt;P&gt;Second, unfortunately, the C# compiler presently has numerous bugs in its cycle detector such that sometimes things which kinda look like cycles but are in fact not cycles are flagged as cycle errors. This just makes it all the more difficult for people to understand what is a legal cycle and what isn't. For example, the compiler today will incorrectly report that this is an illegal base class cycle, even though it clearly is not:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class November&amp;lt;T&amp;gt; {}&lt;BR&gt;public class Romeo : November&amp;lt;Romeo.Sierra.Tango&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp; public class Sierra {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class Tango {}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;I have devised a new (and I believe &lt;EM&gt;correct&lt;/EM&gt;!) cycle detection algorithm implementation, but unfortunately it will not make it into the service release of the C# 3 compiler. It will have to wait for a hypothetical future release. I hope to address the problem of&amp;nbsp;bringing the legal type checker into line with the CLR at the same time.&lt;/P&gt;
&lt;P&gt;Anyway, back to the subject at hand: crazy variance. We have the interfaces defined as above, and then give the compiler a little puzzle to solve:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IC&amp;lt;double&amp;gt; bar = whatever;&lt;BR&gt;IN&amp;lt;IC&amp;lt;string&amp;gt;&amp;gt; foo = bar;&amp;nbsp; // Is this assignment legal? &lt;/SPAN&gt;
&lt;P&gt;I am about to get into a morass of impossible-to-read generic names, so to make it easier on all of us, I am going to from now on abbreviate &lt;SPAN class=code&gt;IN&amp;lt;IC&amp;lt;string&amp;gt;&amp;gt;&lt;/SPAN&gt; as NCS. &lt;SPAN class=code&gt;IC&amp;lt;double&amp;gt;&lt;/SPAN&gt; will be abbreviated as CD. You get the idea I'm sure. &lt;/P&gt;
&lt;P&gt;Similarly, I will notate "is convertible to by implicit reference conversion" by a right-pointing arrow. So the question at hand is true or false: CD→NCS ? &lt;/P&gt;
&lt;P&gt;Well, let’s see. Clearly CD does not go to NCS directly. But (the compiler reasons) maybe CD’s base type does. 
&lt;P&gt;CD’s base type is NNCCD. Does NNCCD→NCS? Well, N is contravariant in its parameter so therefore this boils down to the question, does CS→NCCD ? 
&lt;P&gt;Clearly not directly. But perhaps CS has a base type which goes to NCCD. The base type of CS is NNCCS. So now we have the question does NNCCS→NCCD ? 
&lt;P&gt;Well, N is contravariant in its parameter, so this boils down to the question does CCD→NCCS ? 
&lt;P&gt;Let’s pause and reflect a moment here. 
&lt;P&gt;The compiler has “reduced” the problem of determining the truth of CD→NCS to the problem of determining the truth of CCD→NCCS! If we keep on “reducing” like this then we’ll get to CCCD→NCCCS, CCCCD→NCCCCS, and so on. 
&lt;P&gt;I have a prototype C# compiler which implements variance – if you try this, it says “fatal error, an expression is too complex to compile”. 
&lt;P&gt;I considered implementing an algorithm that is smarter about determining convertibility; the paper I reference below has such an algorithm. (Fortunately, the C# type system is&amp;nbsp;weak enough&amp;nbsp;that&amp;nbsp;determining convertibility of complex types is NOT&amp;nbsp;equivalent to the halting problem; we can find these bogus situations&amp;nbsp;both in principle and in practice. Interestingly, there are type systems in which this problem is equivalent to the halting problem, and type systems for which&amp;nbsp;the computability of convertibility is still an open question.) However, given that we have many other higher priorities, it’s easier to just let the compiler run out of stack space and have a fatal error. These are not realistic scenarios from which we must sensibly recover. 
&lt;P&gt;This is just a taste of some of the ways that the type system gets weird. To get a far more in-depth treatment of this subject, you should read this excellent &lt;A href="http://research.microsoft.com/~akenn/generics/FOOL2007.pdf" mce_href="http://research.microsoft.com/~akenn/generics/FOOL2007.pdf"&gt;Microsoft Research paper&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8461025" 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></item><item><title>Immutability in C# Part Three: A Covariant Immutable Stack</title><link>http://blogs.msdn.com/ericlippert/archive/2007/12/06/immutability-in-c-part-three-a-covariant-immutable-stack.aspx</link><pubDate>Thu, 06 Dec 2007 18:55:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6648007</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6648007.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6648007</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Now suppose we had a hypothetical future version of C# in which interface covariance worked, and we wanted a covariant immutable stack. That is, we want to be able to implicitly convert an &lt;SPAN class=code&gt;IStack&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt; to &lt;SPAN class=code&gt;IStack&amp;lt;Mammal&amp;gt;&lt;/SPAN&gt;. As we've already discussed, this doesn't make much sense in an array, even though doing so is legal in C# today. If you cast a &lt;SPAN class=code&gt;Giraffe[]&lt;/SPAN&gt; to &lt;SPAN class=code&gt;Mammal[]&lt;/SPAN&gt; then you can try to put a &lt;SPAN class=code&gt;Tiger&lt;/SPAN&gt; into the &lt;SPAN class=code&gt;Mammal[]&lt;/SPAN&gt; and it will fail at run time. It seems like the same should be true of stacks -- if you cast an &lt;SPAN class=code&gt;IStack&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt; to &lt;SPAN class=code&gt;IStack&amp;lt;Mammal&amp;gt;&lt;/SPAN&gt; then you can push a &lt;SPAN class=code&gt;Tiger&lt;/SPAN&gt; onto the stack of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s, which should fail, right?&lt;/P&gt;
&lt;P&gt;Maybe. Maybe not.&lt;/P&gt;
&lt;P&gt;The interface we defined the other day is not suitable for covariance because it uses the variant parameter as both an input and and output. Let's get a bit crazy for a minute here -- suppose we got rid of the input on the &lt;SPAN class=code&gt;Push&lt;/SPAN&gt;:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IStack&amp;lt;+T&amp;gt; : IEnumerable&amp;lt;T&amp;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; IStack&amp;lt;T&amp;gt; Pop();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; T Peek();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bool IsEmpty { get; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This interface is now suitable for covariance. If you have a stack of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s and you want to treat it as a stack of &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt;s, you can do so with perfect type safety, since we know that we will never be pushing a &lt;SPAN class=code&gt;Tiger&lt;/SPAN&gt; onto that thing. We'll only be reading off &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s, all of which are &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt;s. This may seem less than useful, but we'll see what we can do:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public sealed class Stack&amp;lt;T&amp;gt; : IStack&amp;lt;T&amp;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; private sealed class EmptyStack : IStack&amp;lt;T&amp;gt;&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; public bool IsEmpty { get { return true; } }&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; public T Peek() { throw new Exception("Empty stack"); }&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; public IStack&amp;lt;T&amp;gt; Pop() { throw new Exception("Empty stack"); }&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; public IEnumerator&amp;lt;T&amp;gt; GetEnumerator() { yield break; }&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; IEnumerator IEnumerable.GetEnumerator() { return this.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; private static readonly EmptyStack empty = new EmptyStack();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IStack&amp;lt;T&amp;gt; Empty { get { return empty; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly T head;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly IStack&amp;lt;T&amp;gt; tail;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private Stack(T head, IStack&amp;lt;T&amp;gt; tail)&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; this.head = head;&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; this.tail = tail;&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; public bool IsEmpty { get { return false; } }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public T Peek() { return head; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IStack&amp;lt;T&amp;gt; Pop() { return tail; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IStack&amp;lt;T&amp;gt; Push(T head, IStack&amp;lt;T&amp;gt; tail) { return new Stack&amp;lt;T&amp;gt;(head, tail); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public IEnumerator&amp;lt;T&amp;gt; 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; for(IStack&amp;lt;T&amp;gt; stack = this; !stack.IsEmpty ; stack = stack.Pop())&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 stack.Peek();&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; IEnumerator IEnumerable.GetEnumerator() {return this.GetEnumerator();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Notice that &lt;SPAN class=code&gt;Push&lt;/SPAN&gt; has disappeared from the empty stack and is static on the nonempty stack, and hey, check it out:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IStack&amp;lt;Giraffe&amp;gt; s1 = Stack&amp;lt;Giraffe&amp;gt;.Empty;&lt;BR&gt;IStack&amp;lt;Giraffe&amp;gt; s2 = Stack&amp;lt;Giraffe&amp;gt;.Push(new Giraffe("Gerry"), s1);&lt;BR&gt;IStack&amp;lt;Giraffe&amp;gt; s3 = Stack&amp;lt;Giraffe&amp;gt;.Push(new Giraffe("Geoffrey"), s2);&lt;BR&gt;IStack&amp;lt;Mammal&amp;gt; s4 = Stack&amp;lt;Mammal&amp;gt;.Push(new Tiger("Tony"), s3);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Oh my goodness, we just pushed a &lt;SPAN class=code&gt;Tiger&lt;/SPAN&gt; onto a stack of &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt;s that is actually a stack of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s underneath, but everything is still typesafe! There is nothing we can do here to cause an exception at runtime in the type system. It all just works. All the stacks of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s continue to be stacks of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s; they're immutable, so they could hardly be anything else.&lt;/P&gt;
&lt;P&gt;This code is pretty ugly though. So...&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static class Extensions&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static IStack&amp;lt;T&amp;gt; Push&amp;lt;T&amp;gt;(this IStack&amp;lt;T&amp;gt; s, T t)&lt;BR&gt;&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; return Stack&amp;lt;T&amp;gt;.Push(t, s);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;and now we can say&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;IStack&amp;lt;Giraffe&amp;gt; sg1 = Stack&amp;lt;Giraffe&amp;gt;.Empty;&lt;BR&gt;IStack&amp;lt;Giraffe&amp;gt; sg2 = s1.Push(new Giraffe("Gerry"));&lt;BR&gt;IStack&amp;lt;Giraffe&amp;gt; sg3 = s2.Push(new Giraffe("Geoffrey"));&lt;BR&gt;IStack&amp;lt;Mammal&amp;gt; sm3 = sg3; // Legal because of covariance.&lt;BR&gt;IStack&amp;lt;Mammal&amp;gt; sm4 = sm3.Push(new Tiger("Tony"));&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Is that slick or what?&lt;/P&gt;
&lt;P&gt;Next time: what about an immutable queue?&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6648007" 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/Immutability/default.aspx">Immutability</category></item><item><title>Covariance and Contravariance in C#, Part Ten: Dealing With Ambiguity</title><link>http://blogs.msdn.com/ericlippert/archive/2007/11/09/covariance-and-contravariance-in-c-part-ten-dealing-with-ambiguity.aspx</link><pubDate>Fri, 09 Nov 2007 22:37:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6026272</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>43</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/6026272.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=6026272</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;OK, I wasn’t quite done. One more variance post!&lt;/P&gt;
&lt;P&gt;Smart people: suppose we made &lt;SPAN class=code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/SPAN&gt; covariant in &lt;SPAN class=code&gt;T&lt;/SPAN&gt;. What should this program fragment do?&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;class C : IEnumerable&amp;lt;Giraffe&amp;gt;, IEnumerable&amp;lt;Turtle&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;Giraffe&amp;gt; IEnumerable&amp;lt;Giraffe&amp;gt;.GetEnumerator() { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return new Giraffe();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerator&amp;lt;Turtle&amp;gt; IEnumerable&amp;lt;Turtle&amp;gt;.GetEnumerator() { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; yield return new Turtle();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;// [etc.]&lt;BR&gt;}&lt;BR&gt;&amp;nbsp;&lt;BR&gt;class Program {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;Animal&amp;gt; animals = new C();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine(animals.First().GetType().ToString()); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Options:&lt;/P&gt;
&lt;P&gt;1) Compile-time error. &lt;BR&gt;2) Run-time error. &lt;BR&gt;3) Always enumerate &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s. &lt;BR&gt;4) Always enumerate &lt;SPAN class=code&gt;Turtle&lt;/SPAN&gt;s. &lt;BR&gt;5) Choose &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s vs &lt;SPAN class=code&gt;Turtle&lt;/SPAN&gt;s at runtime. &lt;BR&gt;6) Other, please specify. &lt;/P&gt;
&lt;P&gt;And if you like any options other than (1), should this be a compile-time warning?&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6026272" 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></item><item><title>Covariance and Contravariance in C#, Part Nine: Breaking Changes</title><link>http://blogs.msdn.com/ericlippert/archive/2007/11/02/covariance-and-contravariance-in-c-part-nine-breaking-changes.aspx</link><pubDate>Fri, 02 Nov 2007 17:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5786612</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>34</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/5786612.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=5786612</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Today in the last entry in my ongoing saga of covariance and contravariance I’ll discuss what breaking changes adding this feature might cause.&lt;/P&gt;
&lt;P&gt;Simply adding variance awareness to the conversion rules should never cause any breaking change. However, the combination of adding variance to the conversion rules and making some types have variant parameters causes potential breaking changes.&lt;/P&gt;
&lt;P&gt;People are generally smart enough to not write:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;if (x is Animal) &lt;BR&gt;&amp;nbsp; DoSomething();&lt;BR&gt;else if (x is Giraffe) &lt;BR&gt;&amp;nbsp; DoSomethingElse(); // never runs&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;because the second condition is entirely subsumed by the first. But today in C# 3.0 it is entirely sensible to write&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;if (x is IEnumerable&amp;lt;Animal&amp;gt;) &lt;BR&gt;&amp;nbsp; DoSomething();&lt;BR&gt;else if (x is IEnumerable&amp;lt;Giraffe&amp;gt;) &lt;BR&gt;&amp;nbsp; DoSomethingElse();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;because there did not used to be any conversion between &lt;SPAN class=code&gt;IEnumerable&amp;lt;Animal&amp;gt;&lt;/SPAN&gt; and &lt;SPAN class=code&gt;IEnumerable&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt;. If we turn on covariance in &lt;SPAN class=code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/SPAN&gt; and the compiled program containing the fragment uses the new library then its behaviour when given an &lt;SPAN class=code&gt;IEnumerable&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt; will change. The object will be assignable to &lt;SPAN class=code&gt;IEnumerable&amp;lt;Animal&amp;gt;&lt;/SPAN&gt;, and therefore the “&lt;SPAN class=code&gt;is&lt;/SPAN&gt;” will report “&lt;SPAN class=code&gt;true&lt;/SPAN&gt;”.&lt;/P&gt;
&lt;P&gt;There is also the issue of existing source code changing semantics or turning compiling programs into erroneous programs. For example, overload resolution may now fail where it used to succeed. If we have:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IBar&amp;lt;T&amp;gt;{} // From some other assembly&lt;BR&gt;...&lt;BR&gt;void M(IBar&amp;lt;Tiger&amp;gt; x){}&lt;BR&gt;void M(IBar&amp;lt;Giraffe&amp;gt; x){}&lt;BR&gt;void M(object x) {}&lt;BR&gt;...&lt;BR&gt;IBar&amp;lt;Animal&amp;gt; y = whatever;&lt;BR&gt;M(y);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Then overload resolution picks the &lt;SPAN class=code&gt;object&lt;/SPAN&gt; version today because it is the sole applicable choice. If we change the definition of &lt;SPAN class=code&gt;IBar&lt;/SPAN&gt; to&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IBar&amp;lt;-T&amp;gt;{} &lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;and recompile then we get an ambiguity error because now all three are applicable and there is no unique best choice.&lt;/P&gt;
&lt;P&gt;We always want to avoid breaking changes if possible, but sometimes new features are sufficiently compelling and the breaks are sufficiently rare that it’s worth it. My intuition is that by turning on interface and delegate variance we would enable many more interesting scenarios than we would break.&lt;/P&gt;
&lt;P&gt;What are your thoughts? Keep in mind that we expect that the vast majority of developers will never have to define the variance of a given type argument, but they may take advantage of variance frequently. Is it worth our while to invest time and energy in this sort of thing for a hypothetical future version of the language?&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5786612" 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/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>Covariance and Contravariance in C#, Part Eight: Syntax Options</title><link>http://blogs.msdn.com/ericlippert/archive/2007/10/31/covariance-and-contravariance-in-c-part-eight-syntax-options.aspx</link><pubDate>Wed, 31 Oct 2007 17:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5767832</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>66</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/5767832.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=5767832</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;As I discussed last time, were we to introduce interface and delegate variance in a hypothetical future version of C# we would&amp;nbsp;need a syntax for it. Here are some possibilities that immediately come to mind.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 1:&lt;/STRONG&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFoo&amp;lt;+T, -U&amp;gt; { T Foo(U u); }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The CLR uses the convention I have been using so far in this series of “&lt;SPAN class=code&gt;+&lt;/SPAN&gt; means covariant, &lt;SPAN class=code&gt;-&lt;/SPAN&gt; means contravariant”. Though this does have some mnemonic value (because &lt;SPAN class=code&gt;+&lt;/SPAN&gt; means “is compatible with a bigger type”), most people (including members of the C# design committee!) have a hard time remembering exactly which is which. &lt;/P&gt;
&lt;P&gt;This convention is also used by the Scala programming language.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 2:&lt;/STRONG&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFoo&amp;lt;T:*, *:U&amp;gt; { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This more graphically indicates “something which is extended by &lt;SPAN class=code&gt;T&lt;/SPAN&gt;” and “something which extends&amp;nbsp;&lt;SPAN class=code&gt;U&lt;/SPAN&gt;”.&amp;nbsp; This is similar to Java’s “wildcard types”, where they say “&lt;SPAN class=code&gt;? extends U&lt;/SPAN&gt;” or “&lt;SPAN class=code&gt;? super T&lt;/SPAN&gt;”.&lt;/P&gt;
&lt;P&gt;Though this isn’t terrible, I think it’s a bit of a conflation of the notions of &lt;EM&gt;extension&lt;/EM&gt; and &lt;EM&gt;assignment compatibility&lt;/EM&gt;. I do not want to imply that &lt;SPAN class=code&gt;IEnumerable&amp;lt;Animal&amp;gt;&lt;/SPAN&gt; is a &lt;EM&gt;base&lt;/EM&gt; of &lt;SPAN class=code&gt;IEnumerable&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt;, even if &lt;SPAN class=code&gt;Animal&lt;/SPAN&gt; is a &lt;EM&gt;base&lt;/EM&gt; of &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;. Rather, I want to say that &lt;SPAN class=code&gt;IEnumerable&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt; is &lt;EM&gt;convertible to&lt;/EM&gt; &lt;SPAN class=code&gt;IEnumerable&amp;lt;Animal&amp;gt;&lt;/SPAN&gt;, or &lt;EM&gt;assignment compatible&lt;/EM&gt;, or some such thing. &lt;STRONG&gt;I don’t want to conceptually overwork the inheritance mechanism.&lt;/STRONG&gt; It's bad enough IMO that we conflate base classes with base interfaces.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 3:&lt;/STRONG&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFoo&amp;lt;T, U&amp;gt; where T: covariant, U: contravariant { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Again, not too bad. The danger here is similar to that of the plus and minus: that no one remembers what “contravariant” and “covariant” mean. This has the benefit at least that you can do a web search on the keywords and get a reasonable explanation.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 4:&lt;/STRONG&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFoo&amp;lt;[Covariant] T, [Contravariant] U&amp;gt;&amp;nbsp; { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Similar to option 3. &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 5:&lt;/STRONG&gt;&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFoo&amp;lt;out T, in U&amp;gt; { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We are taking a different tack with this syntax. In all the options so far we have been describing how the &lt;EM&gt;user&lt;/EM&gt; of the interface may treat the interface with respect to the type system rules for implicit conversions – that is, what are the legal variances on the type parameters. Here we are instead describing this in the language of how the &lt;EM&gt;implementer&lt;/EM&gt; of the interface intends to use the type parameters.&lt;/P&gt;
&lt;P&gt;I like this one a lot; the down side of this is of course that, as I described a few posts ago, you end up with situations like&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;delegate void Meta&amp;lt;out T&amp;gt;(Action&amp;lt;T&amp;gt; action);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;where the "out" &lt;SPAN class=code&gt;T&lt;/SPAN&gt; is clearly used in an input position.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Option 6:&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Do something else I haven’t thought of. Anyone who has bright ideas, please leave comments.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Next time:&lt;/STRONG&gt; what problems are introduced by adding this kind of variance?&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5767832" 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></item><item><title>Covariance and Contravariance in C# Part Seven: Why Do We Need A Syntax At All?</title><link>http://blogs.msdn.com/ericlippert/archive/2007/10/29/covariance-and-contravariance-in-c-part-seven-why-do-we-need-a-syntax-at-all.aspx</link><pubDate>Mon, 29 Oct 2007 17:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5655452</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>20</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/5655452.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=5655452</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Suppose we were to implement generic interface and delegate variance in a hypothetical future version of C#. What, hypothetically, would the syntax look like? There are a bunch of options that we could hypothetically consider. &lt;/P&gt;
&lt;P&gt;Before I get into options though, let’s be bold. What about “no syntax at all”? That is why not just &lt;EM&gt;infer&lt;/EM&gt; &lt;EM&gt;variance on behalf of the user&lt;/EM&gt; such that everything magically just works?&lt;/P&gt;
&lt;P&gt;Unfortunately this doesn’t fly, for several reasons. &lt;/P&gt;
&lt;P&gt;First, it seems to me that variance ought to be something that you &lt;EM&gt;deliberately&lt;/EM&gt; design into your interface or delegate. Making it just start happening with no control by the user works against that goal, and also can introduce breaking changes. (More on those in a later post!) &lt;/P&gt;
&lt;P&gt;Doing so automagically also means that as the development process goes on and methods are added to interfaces, the variance of the interface may change unexpectedly. This could introduce unexpected and far-reaching changes elsewhere in the program. &lt;/P&gt;
&lt;P&gt;Second, attempting to do so introduces a new kind of cycle to the language analysis. We already have to detect things like cycles in base classes, cycles in base interfaces and cycles in generic type constraints, so this is in theory nothing new. But in practice, there are some issues. &lt;/P&gt;
&lt;P&gt;In my previous post I did not discuss what additional restrictions we’d need to put on variant interfaces; one important restriction is that &lt;STRONG&gt;a variant interface which inherits from another variant interface must do so in a manner which does not introduce problems in the type system&lt;/STRONG&gt;. Basically, all the rules for when a type parameter can be covariant or contravariant need to "flow through" to base interfaces. (This is vague, I know. I have a precise&amp;nbsp;formal definition of what all the rules are which I may post at a later date. The exact rules are not important for the purposes of this discussion.) &lt;/P&gt;
&lt;P&gt;For example, suppose the compiler was trying to deduce variance in this program:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IFrob&amp;lt;T&amp;gt; : IBlah&amp;lt;T&amp;gt; { }&lt;BR&gt;interface IBlah&amp;lt;U&amp;gt; {&lt;BR&gt;&amp;nbsp; IFrob&amp;lt;U&amp;gt; Frob();&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We might ask ourselves “is it legal for &lt;SPAN class=code&gt;T&lt;/SPAN&gt; to be variant in &lt;SPAN class=code&gt;IFrob&amp;lt;T&amp;gt;&lt;/SPAN&gt;?” To answer that question, we need to determine whether it is legal for &lt;SPAN class=code&gt;U&lt;/SPAN&gt; to be variant in &lt;SPAN class=code&gt;IBlah&lt;/SPAN&gt;. To answer that question we need to know whether it is legal for &lt;SPAN class=code&gt;U&lt;/SPAN&gt; to be variant in output type &lt;SPAN class=code&gt;IFrob&amp;lt;U&amp;gt;&lt;/SPAN&gt;, and hey, we’re back where we started! &lt;/P&gt;
&lt;P&gt;I would rather the compiler not go into an infinite loop when given this program. But clearly this is a perfectly &lt;EM&gt;legal&lt;/EM&gt; program. When we detect a cycle in base classes, we can throw up our hands and say "you've got an illegal program". We cannot do that here. That complicates matters.&lt;/P&gt;
&lt;P&gt;Third, even if we could figure out a way to solve the cycle problem, we would still have a problem with the case above. Namely, there are three possible logically consistent answers: “both invariant”, “&lt;SPAN class=code&gt;+T, +U&lt;/SPAN&gt;” and “&lt;SPAN class=code&gt;-T, -U&lt;/SPAN&gt;” all produce programs which would be typesafe. How would we choose? &lt;/P&gt;
&lt;P&gt;We could get into even worse situations:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;interface IRezrov&amp;lt;V, W&amp;gt; { &lt;BR&gt;&amp;nbsp; IRezrov&amp;lt;V, W&amp;gt; Rezrov(IRezrov&amp;lt;W, V&amp;gt; x);&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;In this crazy interface we can deduce that “both invariant”, “ &lt;SPAN class=code&gt;&amp;lt;+V, -W&amp;gt;&lt;/SPAN&gt; and &lt;SPAN class=code&gt;&amp;lt;-V, +W&amp;gt;&lt;/SPAN&gt; are all possibilities. Again, how to choose?&lt;/P&gt;
&lt;P&gt;And fourth, even if we could solve all those problems, I suspect that the performance of such an algorithm would be potentially very bad. This has “exponential growth” written all over it. We have other exponential algorithms in the compiler, but I'd rather not add any more if we can avoid it.&lt;/P&gt;
&lt;P&gt;Thus, if we do add interface and delegate variance in some hypothetical future version of C#, we will provide a syntax for it. Next time, some ideas on what that syntax could look like. (If you have bright ideas yourself, feel free to post them in comments!)&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5655452" 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></item><item><title>Covariance and Contravariance in C#, Part Six: Interface Variance</title><link>http://blogs.msdn.com/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx</link><pubDate>Fri, 26 Oct 2007 17:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5627908</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>12</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/5627908.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=5627908</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Over the last few posts I’ve discussed how it is possible to treat a delegate as contravariant in its arguments and covariant in its return type. A delegate is basically just an object which represents a &lt;EM&gt;single&lt;/EM&gt; function call; we can do this same kind of thing to other things which represent function calls. Interfaces, for example, are &lt;EM&gt;contracts which specify what set of function calls are available on a particular object&lt;/EM&gt;.&lt;/P&gt;
&lt;P&gt;This means that we could extend the notion of variance to interface definitions as well, using the same rules as we had for delegates. For example, consider&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IEnumerator&amp;lt;T&amp;gt; : IDisposable, IEnumerator {&lt;BR&gt;&amp;nbsp; new T Current { get; } &lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Here we have a generic interface where the sole use of the parameter is in an output position. We could therefore make the parameter covariant. That would mean that it would be legal to assign an object implementing &lt;SPAN class=code&gt;IEnumerator&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt; to a variable of type &lt;SPAN class=code&gt;IEnumerator&amp;lt;Animal&amp;gt;&lt;/SPAN&gt;. Since the user of that variable will always expect an &lt;SPAN class=code&gt;Animal&lt;/SPAN&gt; to come out, and the actual backing implementation always produces a &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;, everyone is happy.&lt;/P&gt;
&lt;P&gt;Once we’ve got &lt;SPAN class=code&gt;IEnumerator&amp;lt;+T&amp;gt;&lt;/SPAN&gt;, we can then notice that &lt;SPAN class=code&gt;IEnumerable&amp;lt;T&amp;gt;&lt;/SPAN&gt; is defined as:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IEnumerable&amp;lt;T&amp;gt; : IEnumerable {&lt;BR&gt;&amp;nbsp; new IEnumerator&amp;lt;T&amp;gt; GetEnumerator();&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Again, the parameter appears only in an output position, so we could make &lt;SPAN class=code&gt;IEnumerable&amp;lt;+T&amp;gt;&lt;/SPAN&gt; covariant as well. &lt;/P&gt;
&lt;P&gt;This then opens up a whole slew of nice scenarios. Today, this code would fail to compile:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;void FeedAnimals(IEnumerable&amp;lt;Animal&amp;gt; animals) {&lt;BR&gt;&amp;nbsp; foreach(Animal animal in animals)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (animal.Hungry)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Feed(animal);&lt;BR&gt;}&lt;BR&gt;...&lt;BR&gt;IEnumerable&amp;lt;Giraffe&amp;gt; adultGiraffes = from g in giraffes where g.Age &amp;gt; 5 select g;&lt;BR&gt;FeedAnimals(adultGiraffes);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Because &lt;SPAN class=code&gt;adultGiraffes&lt;/SPAN&gt; implements &lt;SPAN class=code&gt;IEnumerable&amp;lt;Giraffe&amp;gt;&lt;/SPAN&gt;, not &lt;SPAN class=code&gt;IEnumerable&amp;lt;Animal&amp;gt;&lt;/SPAN&gt;. With C# 3.0 you’d have to do a silly and expensive casting operation to make this compile, something like:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;FeedAnimals(adultGiraffes.Cast&amp;lt;Animal&amp;gt;());&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;or &lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;FeedAnimals(from g in adultGiraffes select (Animal)g);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Or whatever. This explicit typing should not be necessary. Unlike arrays (which are read-write) it is perfectly typesafe to treat a read-only list of giraffes as a list of animals.&lt;/P&gt;
&lt;P&gt;Similarly, we could make&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface IComparer&amp;lt;-T&amp;gt; {&lt;BR&gt;&amp;nbsp; int Compare(T x, T y);&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;into a contravariant interface, since the type parameter is used only in &lt;EM&gt;input&lt;/EM&gt; positions. You could then implement an object which compares two &lt;SPAN class=code&gt;Animal&lt;/SPAN&gt;s and use it in a context where you need an object which compares two &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;s without worrying about type system problems.&lt;/P&gt;
&lt;P&gt;Next time: Suppose we were to do interface and delegate variance in a hypothetical future version of C#. What would the syntax look like? Is this goofy plus and minus really the best we can do?&amp;nbsp;Do we need any syntax at all?&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5627908" 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></item></channel></rss>