<?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>Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx</link><description>C# implements variance in two ways. Today, the broken way. 
 Ever since C# 1.0, arrays where the element type is a reference type are covariant . This is perfectly legal: 
 Animal[] animals = new Giraffe[10]; 
 Since Giraffe is smaller than Animal</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#10350654</link><pubDate>Tue, 18 Sep 2012 23:54:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10350654</guid><dc:creator>Cline</dc:creator><description>&lt;p&gt;Personally I love array covariance, and wish generic lists were covariant. &amp;nbsp;IEnumerables would be syntactically more tolerable if they were addressable like lists. &amp;nbsp;In other words if you don&amp;#39;t want array covariance, a dedicated IReadableList might have been worthwhile. &amp;nbsp;&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10350654" width="1" height="1"&gt;</description></item><item><title>Covariance and Contravariance in C#, Part Four: Real Delegate Variance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#9629328</link><pubDate>Tue, 19 May 2009 22:57:37 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9629328</guid><dc:creator>Fabulous Adventures In Coding</dc:creator><description>&lt;p&gt;In the last two posts I discussed the two kinds of variance that C# already has -- array covariance and&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9629328" width="1" height="1"&gt;</description></item><item><title>WAW!!! What a serie of blog posts for "Covariance and Contravariance" - C# Future...</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#9236181</link><pubDate>Thu, 18 Dec 2008 16:24:39 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9236181</guid><dc:creator>Journal of Abu Sayed Mohammad Ismail</dc:creator><description>&lt;p&gt;So nicely step by step blogged by Eric Lippert for &amp;amp;quot;Covariance and Contravariance&amp;amp;quot; as &amp;amp;quot;Fabulous&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9236181" width="1" height="1"&gt;</description></item><item><title>Community Convergence XXXIV</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5755866</link><pubDate>Mon, 29 Oct 2007 08:38:38 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5755866</guid><dc:creator>Charlie Calvert's Community Blog</dc:creator><description>&lt;p&gt;Welcome to the Thirty-Fourth issue of Community Convergence. This is a time when the team is in transition.&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5755866" width="1" height="1"&gt;</description></item><item><title>Community Convergence XXXIV</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5755787</link><pubDate>Mon, 29 Oct 2007 08:35:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5755787</guid><dc:creator>Charlie Calvert's Community Blog</dc:creator><description>&lt;p&gt;Welcome to the Thirty-Fourth issue of Community Convergence. This is a time when the team is in transition.&lt;/p&gt;
&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5755787" width="1" height="1"&gt;</description></item><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5510271</link><pubDate>Thu, 18 Oct 2007 19:35:06 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5510271</guid><dc:creator>Grant</dc:creator><description>&lt;p&gt;To elaborate on my original example, should the following code throw a compile-time error, a run-time error, or do copy-on-write? &amp;nbsp;I really am curious to see what you think the right way is. &amp;nbsp;I've been goofing around a lot with algebraic data types lately and contemplating the differences between ADTs and objects, and when each is appropriate. &amp;nbsp;So far, the practical rule of thumb I've come up with is: If you find yourself doing RTTI, that object hierarchy should've been represented with ADTs.&lt;/p&gt;
&lt;p&gt;Giraffe[] giraffes = new Giraffe[10];&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;// somewhere else&lt;/p&gt;
&lt;p&gt;Animal[] animals = giraffes;&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;amimals.append(new Turtle()); /* not sure if it's really valid C#, but you get the point */&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5510271" width="1" height="1"&gt;</description></item><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5509794</link><pubDate>Thu, 18 Oct 2007 18:41:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5509794</guid><dc:creator>Eric Lippert</dc:creator><description>&lt;p&gt;A good question. &lt;/p&gt;
&lt;p&gt;In this case the covariance is perfectly safe because you are treating arrays as read-only for the purposes of this method. It's only when you try to write to the array that you have a potential problem, and you don't do that here.&lt;/p&gt;
&lt;p&gt;The way to get safe covariance is to separate out the read-only operations into interfaces and make them covaraint. &amp;nbsp;If you wrote your program to take two IEnumerable&amp;lt;object&amp;gt; objects and we could somehow make IEnumerable&amp;lt;T&amp;gt; covariant in T then that would be perfectly type safe. IEnumerable does not allow you to write to the object, only read from it, so it is safe for covariance. &amp;nbsp;You could then pass your IEnumerable&amp;lt;Giraffe&amp;gt; and IEnumerable&amp;lt;Animal&amp;gt; to the function and it would be just fine.&lt;/p&gt;
&lt;p&gt;Of course, I have just spoiled the surprise; that is precisely where this series of posts is heading.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5509794" width="1" height="1"&gt;</description></item><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5509693</link><pubDate>Thu, 18 Oct 2007 18:30:07 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5509693</guid><dc:creator>Gabe</dc:creator><description>&lt;p&gt;Without the type of covariance as implemented in C#, how would I write a function like this:&lt;/p&gt;
&lt;p&gt;static bool ArrayEquals(object[] a, object[] b)&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt;;;if (a.Length != b.Length) return false;&lt;/p&gt;
&lt;p&gt;;;for (int i = 0; i &amp;lt; a.Length; i++) if (!a[i].Equals(b[i]) return false;&lt;/p&gt;
&lt;p&gt;;;return true;&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5509693" width="1" height="1"&gt;</description></item><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5500538</link><pubDate>Thu, 18 Oct 2007 01:38:15 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5500538</guid><dc:creator>Eric Lippert</dc:creator><description>&lt;p&gt;I agree with you that this situation is extremely irksome. &amp;nbsp;However, it is one that we are stuck with.&lt;/p&gt;
&lt;p&gt;However, it _is_ covariance. I have a partial ordering on types (CLR assignment compatibility) and an operator from type to type (&amp;quot;make an array type&amp;quot;) which preserves the ordering. That's the _definition_ of &amp;quot;covariant operator&amp;quot;. &lt;/p&gt;
&lt;p&gt;Perhaps you prefer &amp;quot;always-typesafe liskov-style substitution&amp;quot; as the basis for a partial ordering, rather than the sometimes-not-typesafe ordering that I've chosen. If that's your choice of partial ordering, then I agree with you, making arrays is not covariant. But that's not the partial ordering I'm choosing for the purposes of this series of articles.&lt;/p&gt;
&lt;p&gt;You theory guys seem bound and determined to reject my choice of partial ordering today. That is your right, of course, but since I'm the guy who is going to have to implement this in a compiler that targets the CLR, choosing &amp;quot;assignment compatible in the CLR&amp;quot; is a highly pragmatic choice for me.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5500538" width="1" height="1"&gt;</description></item><item><title>re: Covariance and Contravariance in C#, Part Two: Array Covariance</title><link>http://blogs.msdn.com/b/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx#5499316</link><pubDate>Thu, 18 Oct 2007 00:10:04 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5499316</guid><dc:creator>Adam</dc:creator><description>&lt;p&gt;This is not actually covariance.&lt;/p&gt;
&lt;p&gt;The type of consumers that can accept Giraffes is &amp;quot;smaller&amp;quot; than the type of consumers that can accept Animals: if a consumer can accept an Animal, then it can accept a Giraffe, but not vice versa.&lt;/p&gt;
&lt;p&gt;For example, the type of write-only arrays of Giraffes should be a subtype of the type of write-only arrays of Animals.&lt;/p&gt;
&lt;p&gt;The type of producers that can make Giraffes is &amp;quot;larger&amp;quot; than the type of producers that can make Animals: if a producer can make Giraffes, then it can make Animals.&lt;/p&gt;
&lt;p&gt;For example, the type of read-only arrays of Animals should be a subtype of the type of read-only arrays of Giraffes.&lt;/p&gt;
&lt;p&gt;Since an array can both produce (e.g. animals[0]) and consume (e.g. animals[0]=myanimal), Animal[] should be neither a subtype nor a supertype of Giraffe[].&lt;/p&gt;
&lt;p&gt;So to address the question of how the following should be handled:&lt;/p&gt;
&lt;p&gt;Giraffe[] giraffes = new Giraffe[10];&lt;/p&gt;
&lt;p&gt;I say it should be handled with a compile-time error.&lt;/p&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5499316" width="1" height="1"&gt;</description></item></channel></rss>