<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Jon Skeet: Coding Blog : Evil Code, C# 4</title><link>http://msmvps.com/blogs/jon_skeet/archive/tags/Evil+Code/C_2300_+4/default.aspx</link><description>Tags: Evil Code, C# 4</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Evil Code of the Day: variance and overloading</title><link>http://msmvps.com/blogs/jon_skeet/archive/2009/07/13/evil-code-of-the-day-variance-and-overloading.aspx</link><pubDate>Mon, 13 Jul 2009 16:10:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1700112</guid><dc:creator>skeet</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/rsscomments.aspx?PostID=1700112</wfw:commentRss><wfw:comment xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://msmvps.com/blogs/jon_skeet/commentapi.aspx?PostID=1700112</wfw:comment><comments>http://msmvps.com/blogs/jon_skeet/archive/2009/07/13/evil-code-of-the-day-variance-and-overloading.aspx#comments</comments><description>&lt;p&gt;(Note that this kind of breakage was &lt;a href="http://blogs.msdn.com/ericlippert/archive/2007/11/02/covariance-and-contravariance-in-c-part-nine-breaking-changes.aspx"&gt;mentioned a long time ago in Eric Lippert&amp;#39;s blog&lt;/a&gt;, although not in this exact form.)&lt;/p&gt;
&lt;p&gt;Whenever a conversion becomes available where it wasn&amp;#39;t before, overload resolution can change its behaviour. From C# 1 to C# 2 this happened due to delegate variance with method group conversions - now the same thing is true for generic variance for interfaces.&lt;/p&gt;
&lt;p&gt;What does the following code print?&lt;/p&gt;
&lt;div class="code"&gt; &lt;span class="Namespace"&gt;using&lt;/span&gt;&amp;nbsp;System;&lt;br /&gt; &lt;span class="Namespace"&gt;using&lt;/span&gt;&amp;nbsp;System.Collections.Generic;&lt;br /&gt; &lt;br /&gt; &lt;span class="ReferenceType"&gt;class&lt;/span&gt;&amp;nbsp;Base&lt;br /&gt; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt;&amp;nbsp;Foo(IEnumerable&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;strings)&lt;br /&gt; &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;Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Strings&amp;quot;&lt;/span&gt;);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span class="ReferenceType"&gt;class&lt;/span&gt;&amp;nbsp;Derived&amp;nbsp;:&amp;nbsp;Base&lt;br /&gt; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Modifier"&gt;public&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt;&amp;nbsp;Foo(IEnumerable&amp;lt;&lt;span class="ReferenceType"&gt;object&lt;/span&gt;&amp;gt;&amp;nbsp;objects)&lt;br /&gt; &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;Console.WriteLine(&lt;span class="String"&gt;&amp;quot;Objects&amp;quot;&lt;/span&gt;);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; &lt;span class="ReferenceType"&gt;class&lt;/span&gt;&amp;nbsp;Test&lt;br /&gt; {&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Modifier"&gt;static&lt;/span&gt;&amp;nbsp;&lt;span class="ValueType"&gt;void&lt;/span&gt;&amp;nbsp;Main()&lt;br /&gt; &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;List&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;&amp;nbsp;strings&amp;nbsp;=&amp;nbsp;&lt;span class="Keyword"&gt;new&lt;/span&gt;&amp;nbsp;List&amp;lt;&lt;span class="ReferenceType"&gt;string&lt;/span&gt;&amp;gt;();&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span class="Keyword"&gt;new&lt;/span&gt;&amp;nbsp;Derived().Foo(strings);&lt;br /&gt; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt; } &lt;/div&gt;
&lt;p&gt;The correct answer is &amp;quot;it depends on which version of C# &lt;em&gt;and&lt;/em&gt; .NET framework you&amp;#39;re using.&amp;quot;&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re using C# 4.0 and .NET 4.0, then IEnumerable&amp;lt;T&amp;gt; is covariant: there&amp;#39;s an implicit conversion from IEnumerable&amp;lt;string&amp;gt; to IEnumerable&amp;lt;object&amp;gt;, so the derived overload is used.&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re using C# 4.0 but .NET 3.5 or earlier then the compiler still knows about variance in general, but the interface in the framework doesn&amp;#39;t have the appropriate metadata to indicate it, so there&amp;#39;s no conversion available, and the base class overload is used.&lt;/p&gt;
&lt;p&gt;If you&amp;#39;re using C# 3.0 or earlier then the compiler doesn&amp;#39;t know about generic variance at all, so again the base class overload is used.&lt;/p&gt;
&lt;p&gt;So, this is a breaking change, and a fairly subtle one at that - and unlike the method group conversion in .NET 2.0, the compiler in .NET 4.0 beta 1 doesn&amp;#39;t issue a warning about it. I&amp;#39;ll edit this post when there&amp;#39;s an appropriate Connect ticket about it...&lt;/p&gt;
&lt;p&gt;In general though, I&amp;#39;d say it&amp;#39;s worth avoiding overloading a method declared in a base class unless you really have to. In particular, overloading it using the same number of parameters but more general ones seems to be a recipe for unreadable code.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://msmvps.com/aggbug.aspx?PostID=1700112" width="1" height="1"&gt;</description><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/C_2300_+4/default.aspx">C# 4</category><category domain="http://msmvps.com/blogs/jon_skeet/archive/tags/Evil+Code/default.aspx">Evil Code</category></item></channel></rss>