<?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 : Overload Resolution</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx</link><description>Tags: Overload Resolution</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Constraints are not part of the signature</title><link>http://blogs.msdn.com/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx</link><pubDate>Thu, 10 Dec 2009 17:31:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9932645</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>75</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9932645.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9932645</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;What happens here? &lt;SPAN class=code&gt;
&lt;P&gt;class Animal { } &lt;BR&gt;class Mammal : Animal { } &lt;BR&gt;class Giraffe : Mammal { }&lt;BR&gt;class Reptile : Animal { } &lt;BR&gt;…&lt;BR&gt;static void Foo&amp;lt;T&amp;gt;(T t) where T : Reptile { }&lt;BR&gt;static void Foo(Animal animal) { }&lt;BR&gt;static void Main() &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Foo(new Giraffe()); &lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Most people assume that overload resolution will choose the second overload. In fact, this program produces a compile error saying that T cannot be Giraffe. Is this a compiler bug?&lt;/P&gt;
&lt;P&gt;No, this behaviour is correct according to the spec. First we attempt to determine the candidate set. Clearly the second overload is a member of the candidate set. The first overload is a member of the candidate set if type inference succeeds.&lt;/P&gt;
&lt;P&gt;The method type inference algorithm considers &lt;STRONG&gt;only&lt;/STRONG&gt; whether the method type arguments can be consistently inferred from the types of the arguments. Method type inference cares not a bit about whether the resulting method is malformed in some other way. Its only job is to work out the best possible type arguments given the arguments to the method. Clearly the best type for T is Giraffe, so that’s what we infer. &lt;/P&gt;
&lt;P&gt;So we now have two methods in the candidate set, Foo&amp;lt;Giraffe&amp;gt;, and the second overload. Which is better?&lt;/P&gt;
&lt;P&gt;Again, overload resolution looks only at the arguments you passed in, and compares them to the types of all the candidates. The argument is of type Giraffe. We have a choice: argument of type Giraffe goes to parameter of type Giraffe, or argument of type Giraffe goes to parameter of type Animal. Clearly the former is better; it’s an exact match.&lt;/P&gt;
&lt;P&gt;Therefore we discard the second overload because it is worse than another candidate. That leaves one candidate left, which is an exact match. Only then, after overload resolution, do we check to see whether the generic constraints are violated. &lt;/P&gt;
&lt;P&gt;When I try to explain this to people, they often bring up this portion of the specification as evidence that I am wrong, wrong, wrong:&lt;/P&gt;&lt;SPAN class=spec&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;If F is generic and M has no type argument list, F is a candidate when:&lt;BR&gt;1) type inference succeeds, and &lt;BR&gt;2) once the inferred type arguments are substituted for the corresponding method type parameters, &lt;EM&gt;all constructed types in the parameter list of F satisfy their constraints&lt;/EM&gt;, and the parameter list of F is applicable with respect to A. [emphasis added]&lt;/SPAN&gt; &lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;This appears at first glance to say that Foo&amp;lt;Giraffe&amp;gt; cannot be a candidate because the constraints are not satisfied. That is a misreading of the specification; the bit “in the parameter list” is referring to the &lt;EM&gt;formal&lt;/EM&gt; &lt;EM&gt;parameter&lt;/EM&gt; list, not the &lt;EM&gt;type parameter&lt;/EM&gt; list.&lt;/P&gt;
&lt;P&gt;Let me give you an example of where this rule comes into play, so that it’s clear. Suppose we have&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;class C&amp;lt;T&amp;gt; where T : Mammal {}&lt;BR&gt;…&lt;BR&gt;static void Bar&amp;lt;T&amp;gt;(T t, C&amp;lt;T&amp;gt; c) {}&lt;BR&gt;static void Bar(Animal animal, string s) { }&lt;BR&gt;…&lt;BR&gt;Bar(new Iguana(), null);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Type inference infers that Bar&amp;lt;Iguana&amp;gt; might be a candidate. But that would mean that we are calling a method that converts null to C&amp;lt;Iguana&amp;gt;, which violates the constraint in the declaration of C&amp;lt;T&amp;gt;. Therefore the results of type inference are discarded, and Bar&amp;lt;Iguana&amp;gt; is not added to the candidate set. &lt;/P&gt;
&lt;P&gt;So if that’s not the relevant bit of the spec, what is? The relevant bit happens &lt;EM&gt;after&lt;/EM&gt; the best method has been determined, not before.&lt;/P&gt;&lt;SPAN class=spec&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;If the best method is a generic method, the type arguments (supplied or inferred) are checked against the constraints declared on the generic method. If any type argument does not satisfy the corresponding constraints on the type parameter, a compile-time error occurs. &lt;/SPAN&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;It is often surprising to people that an invalid method can be chosen as the best method, chosen over a less good method that would be valid. (*) &lt;STRONG&gt;The principle here is overload resolution (and method type inference) find the best possible match between a list of arguments and each candidate method’s list of formal parameters.&lt;/STRONG&gt; That is, they look at the &lt;EM&gt;signature&lt;/EM&gt; of the candidate method. If the best possible match between the arguments and the signature of the method identify a method that is for whatever reason not possible to call, then &lt;EM&gt;you need to choose your arguments more carefully so that the bad thing is no longer the best match&lt;/EM&gt;. We figure that you want to be told that there's a problem, rather than silently falling back to a less-good choice. 
&lt;P&gt;UPDATE: My Twilight-reading friend Jen from a couple episodes back points out that this is not just good language design, it's good dating advice. &lt;STRONG&gt;If the best possible match between your criteria and an available guy on Match.com identifies a guy who, for whatever reason, is impossible to call, then you need to choose your criteria more carefully so that the bad guy is no longer the best match.&lt;/STRONG&gt;&amp;nbsp; Words to live by. 
&lt;HR&gt;

&lt;P&gt;(*) I already discussed the related situation of how it is the case that &lt;A href="http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx"&gt;we can choose a static method over an instance method even when there’s no hope of the static method being the right one.&lt;/A&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9932645" 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/Type+Inference/default.aspx">Type Inference</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Relationships/default.aspx">Relationships</category></item><item><title>What's the difference, part one: Generics are not templates</title><link>http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx</link><pubDate>Thu, 30 Jul 2009 16:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9803982</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>32</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9803982.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9803982</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Because I'm a geek, I enjoy&amp;nbsp;learning about the sometimes-subtle differences between easily-confused things. For example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;I'm still not super-clear in my head on the differences between a &lt;STRONG&gt;hub&lt;/STRONG&gt;, &lt;STRONG&gt;router&lt;/STRONG&gt; and &lt;STRONG&gt;switch&lt;/STRONG&gt; and how it relates to the gnomes that live inside of each.&lt;/LI&gt;
&lt;LI&gt;Hunks of minerals found in nature are &lt;STRONG&gt;rocks&lt;/STRONG&gt;; as soon as you put them in a garden or build a bridge out of them, suddenly they become &lt;STRONG&gt;stones&lt;/STRONG&gt;.&lt;/LI&gt;
&lt;LI&gt;When a &lt;STRONG&gt;pig&lt;/STRONG&gt; hits 120 pounds, it's a &lt;STRONG&gt;hog&lt;/STRONG&gt;.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;I thought I might do an occasional series on easily confounded concepts in programming language design.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here’s a question I get fairly often:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public static void DoIt&amp;lt;T&amp;gt;(T t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReallyDoIt(t);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(string s)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("string");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt&amp;lt;T&amp;gt;(T t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("everything else");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What happens when you call &lt;SPAN class=code&gt;C.DoIt&amp;lt;string&amp;gt;&lt;/SPAN&gt;? Many people expected that “string” is printed, when in fact “everything else” is always printed, no matter what T is. &lt;/P&gt;
&lt;P&gt;The C# specification says that when you have a choice between calling &lt;SPAN class=code&gt;ReallyDoIt&amp;lt;string&amp;gt;(string)&lt;/SPAN&gt; and &lt;SPAN class=code&gt;ReallyDoIt(string)&lt;/SPAN&gt; – that is, when the choice is between two methods that have identical signatures, but one gets that signature via generic substitution – then we pick the “natural” signature over the “substituted” signature. Why don’t we do that in this case?&lt;/P&gt;
&lt;P&gt;Because that’s not the choice that is presented. If you had said&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;ReallyDoIt("hello world");&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;then we would pick the “natural” version. But you didn’t pass something known to the compiler to be a string. You passed something known to be a T, an unconstrained type parameter, and hence it could be anything. So, the overload resolution algorithm reasons, is there a method that can always take anything? Yes, there is. &lt;/P&gt;
&lt;P&gt;This illustrates that &lt;STRONG&gt;generics&lt;/STRONG&gt; in C# are not like &lt;STRONG&gt;templates&lt;/STRONG&gt; in C++. You can think of templates as a fancy-pants search-and-replace mechanism. When you say &lt;SPAN class=code&gt;DoIt&amp;lt;string&amp;gt;&lt;/SPAN&gt; in a template, the compiler conceptually searches out all uses of “T”, replaces them with “string”, and then compiles the resulting source code. Overload resolution proceeds with the substituted type arguments known, and the generated code then reflects the results of that overload resolution.&lt;/P&gt;
&lt;P&gt;That’s not how generic types work; generic types are, well, &lt;EM&gt;generic&lt;/EM&gt;. We do the overload resolution &lt;STRONG&gt;once&lt;/STRONG&gt; and bake in the result. We do not change it at runtime when someone, possibly in an entirely different assembly, uses string as a type argument to the method. The IL we’ve generated for the generic type already has the method its going to call picked out. The jitter does not say “well, I happen to know that if we asked the C# compiler to execute right now with this additional information then it would have picked a different overload. Let me rewrite the generated code to ignore the code that the C# compiler originally generated...” The jitter knows nothing about the rules of C#.&lt;/P&gt;
&lt;P&gt;Essentially, the case above is no different from this:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public static void DoIt(object t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ReallyDoIt(t);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(string s)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("string");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; private static void ReallyDoIt(object t)&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Console.WriteLine("everything else");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;When the compiler generates the code for the call to &lt;SPAN class=code&gt;ReallyDoIt&lt;/SPAN&gt;, it picks the object version because that’s the best it can do. If someone calls this with a string, then it still goes to the object version.&lt;/P&gt;
&lt;P&gt;Now, if you do want overload resolution to be re-executed at runtime based on the runtime types of the arguments, we can do that for you; that’s what the new “dynamic” feature does in C# 4.0. Just replace “object” with “dynamic” and when you make a call involving that object, we’ll run the overload resolution algorithm at runtime and dynamically spit code that calls the method that the compiler would have picked, had it known all the runtime types at compile time.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9803982" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_+4.0/default.aspx">C# 4.0</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/What_2700_s+The+Difference_3F00_/default.aspx">What's The Difference?</category></item><item><title>Color Color</title><link>http://blogs.msdn.com/ericlippert/archive/2009/07/06/color-color.aspx</link><pubDate>Mon, 06 Jul 2009 16:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9762614</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/9762614.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=9762614</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Pop quiz: What does the following code do when compiled and run?&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;class C&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void M(string x)&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; System.Console.WriteLine("static M(string)");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void M(object s)&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; System.Console.WriteLine("M(object)");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;}&lt;BR&gt;class Program&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C c = new C();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c.M("hello");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;(1) writes static M(string)&lt;BR&gt;(2) writes M(object)&lt;BR&gt;(3) uh, dude, this code doesn’t even compile much less run&lt;BR&gt;(4) something else 
&lt;P&gt;Think about that for a bit and then try it and see if you were right. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;. 
&lt;P&gt;In option (1), the compiler could decide that the best match is the static one and let you call it through the instance, ignoring the instance value. In option (2), the compiler could decide that the object version is the best match and ignore the static one, even though the argument match is better. But neither of those actually happens; the rules of C# say that the compiler should &lt;STRONG&gt;pick the best match based on the arguments&lt;/STRONG&gt;, and &lt;EM&gt;then&lt;/EM&gt; disallow static calls that are through an instance! The actual result here is therefore (3): &lt;SPAN class=code&gt;
&lt;P&gt;error CS0176: Member 'C.M(string)' cannot be accessed with an instance reference; qualify it with a type name instead &lt;/SPAN&gt;
&lt;P&gt;What is up with this craziness? If you believe that the rule “static methods should never be accessed through instances” is a good rule – and it seems reasonable – then why doesn’t overload resolution remove the static methods from the candidate set when called through an instance? Why does it even allow the “string” version to be an applicable candidate in the first place, if the compiler knows that it can never possibly work? 
&lt;P&gt;I agree that this seems really goofy at first. 
&lt;P&gt;To explain why this is not quite as dumb as it seems, consider the following variation on the problem. Class C stays the same. &lt;SPAN class=code&gt;
&lt;P&gt;class B&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; public C C = new C();&lt;BR&gt;&amp;nbsp; public void N()&lt;BR&gt;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C.M("hello");&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What does a call to N on an instance of B do?&lt;/P&gt;
&lt;P&gt;(1) writes static M(string)&lt;BR&gt;(2) writes M(object)&lt;BR&gt;(3) compilation error&lt;BR&gt;(4) something else&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;.&lt;/P&gt;
&lt;P&gt;A bit trickier now, isn’t it? Does C.M mean “call instance method M on the instance stored in this.C?” or does it mean “call static method M on type C”? Both are applicable!&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Because of our goofy rule we do the right thing in this case.&lt;/STRONG&gt; We first resolve the call based solely on the arguments and determine that the static method is the best match. Then we check to see if the “receiver” at the call site can be interpreted as being through the type. It can. So we make the static call and write “static M(string)”. &lt;STRONG&gt;If the instance version had been the best match then we would successfully call the instance method through the property.&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;So the reason that the compiler does not remove static methods when calling through an instance is because the compiler does not necessarily know that you are calling through an instance. Because there are situations where it is ambiguous whether you’re calling through an instance or a type, we defer deciding which you meant until the best method has been selected.&lt;/P&gt;
&lt;P&gt;Now, one could make the argument that in our first case, the receiver cannot &lt;EM&gt;possibly&lt;/EM&gt; be a type. We &lt;EM&gt;could&lt;/EM&gt; have further complicated the language semantics by having &lt;EM&gt;three&lt;/EM&gt; overload resolution rules, one for when the receiver is &lt;EM&gt;known to be a type&lt;/EM&gt;, one for when the receiver is &lt;EM&gt;known to not be a type&lt;/EM&gt;, and one for when the receiver &lt;EM&gt;might or might not be a type&lt;/EM&gt;. But rather than complicate the language further, we made the pragmatic choice of simply deferring the staticness check until after the bestness check. That’s not perfect but it is good enough for most cases and it solves the common problem.&lt;/P&gt;
&lt;P&gt;The common problem is the situation that arises when you have a&lt;STRONG&gt; property of a type with the same name&lt;/STRONG&gt;, and then try to call either a static method on the type, or an instance method on the property. (This can also happen with locals and fields, but local and field names typically differ&amp;nbsp;in case from the names of their&amp;nbsp;types.)&amp;nbsp;The canonical motivating example is a public property named Color of type Color, so we call this “&lt;STRONG&gt;the Color Color problem&lt;/STRONG&gt;”. &lt;/P&gt;
&lt;P&gt;In real situations the instance and static methods typically have different names, so in the typical scenario you never end up calling an instance method when you expect to call a static method, or vice versa. The case I presented today with a name collision between a static and an instance method is relatively rare.&lt;/P&gt;
&lt;P&gt;If you’re interested in reading the exact rules for how the compiler deals with the Color Color problem, see section 7.5.4.1 of the C# 3.0 specification. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9762614" 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/Puzzles/default.aspx">Puzzles</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Static+Methods/default.aspx">Static Methods</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/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Color+Color/default.aspx">Color Color</category></item><item><title>Method Type Inference Changes, Part One</title><link>http://blogs.msdn.com/ericlippert/archive/2008/06/17/method-type-inference-changes-part-one.aspx</link><pubDate>Tue, 17 Jun 2008 18:20:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8611835</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8611835.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8611835</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;I want to start this by discussing the purpose of method type inference, and clearing up some potential misunderstandings about type inference errors.&lt;/P&gt;
&lt;P&gt;First off though, a brief note on nomenclature. Throughout this series when I say "type inference" I mean "method type inference", not any of the other forms of type inference we have in C# 3.0. (Implicitly typed locals, implicitly typed arrays, and so on.)&lt;/P&gt;
&lt;P&gt;The purpose of type inference is to allow generic methods to be called without explicitly specifying the generic types. For example, if you have a generic method&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static&amp;nbsp;T Largest&amp;lt;T&amp;gt;(IEnumerable&amp;lt;T&amp;gt; list) where T : IComparable&amp;lt;T&amp;gt; { ... }&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;then it would be nice to be able to say&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;decimal&amp;nbsp;maxPrice = Largest(prices);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;without having to say redundant information:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;decimal&amp;nbsp;maxPrice = Largest&amp;lt;decimal&amp;gt;(prices);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;This was useful in C# 2.0, but with the advent of extension methods and query comprehensions in C# 3.0, it is downright vital. If we made Largest into an extension method then clearly you want to be able to say&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;from customer in customers &lt;BR&gt;from invoices in customers.invoices&lt;BR&gt;select invoices.prices.Largest();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;and not have to insert this ugly mechanism information into your lovely semantic query:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;from customer in customers &lt;BR&gt;from invoices in customers.invoices&lt;BR&gt;select invoices.prices.Largest&amp;lt;decimal&amp;gt;();&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;When you call a method without an explicit argument list, overload resolution must figure out which method you meant to call. The way type inference works with overload resolution is that all methods of that name are put into a pool called the candidate set. If any of them are generic, we run a type inference algorithm to see if the generic type arguments can be inferred for the method. If they can, then the constructed generic method stays in the candidate set; if inference fails then it is removed. Then all methods which are inapplicable -- that is, the arguments cannot be converted to the parameter types -- are removed. Of the remaining applicable candidates, either a unique best candidate is chosen. If a unique best candidate cannot be identified then overload resolution fails.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Note that type inference failure is not actually an error in of itself. However, type inference failure (or success!) might cause real errors downstream in a number of ways. For example:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;if type inference fails and the candidate set becomes empty as a result, then overload resolution fails&lt;/LI&gt;
&lt;LI&gt;if type inference fails when the user intended the generic method to be the chosen one, and the remaining candidates have no unique best member, then overload resolution fails&lt;/LI&gt;
&lt;LI&gt;if type inference succeeds when it wasn't expected to then there might be more methods in the candidate set than expected. If the inferred method ties for "bestness" with another candidate then overload resolution fails. (The tiebreaker rules in overload resolution are designed to avoid this scenario, but it is still possible in contrived situations.)&lt;/LI&gt;&lt;/UL&gt;
&lt;P mce_keep="true"&gt;This then brings up the question of what error message to display when overload resolution fails. In C# 2.0 we have a heuristic which tries to detect when overload resolution failed because of the first case (which is the most common of the three cases.) In those cases it gives an error message that says "type inference failed" rather than "overload resolution failed". Even though the actual error as far as the language specification is concerned is that the candidate set contained no unique best applicable member, the user typically thinks of the cause of the error as being type inference failure in many cases, so we try to do a good job of reporting that.&lt;/P&gt;
&lt;P mce_keep="true"&gt;It works pretty well in C# 2.0, but we struggled with this a lot in C# 3.0. Suppose you end up in a situation where you have a query:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P mce_keep="true"&gt;IEnumerable&amp;lt;Customer&amp;gt; customers = ...;&lt;BR&gt;var&amp;nbsp;firstNames = from c in customers select c.FristName;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P mce_keep="true"&gt;Oops. That is going to be translated into &lt;SPAN class=code&gt;customers.Select(c=&amp;gt;c.FristName)&lt;/SPAN&gt;. There are no methods named "Select" on &lt;SPAN class=code&gt;IEnumerable&amp;lt;Customer&amp;gt;&lt;/SPAN&gt;, we look for extension methods and find &lt;SPAN class=code&gt;Enumerable.Select&amp;lt;T, R&amp;gt;(this IEnumerable&amp;lt;T&amp;gt; list, Func&amp;lt;T, R&amp;gt; selector)&lt;/SPAN&gt;. Type inference infers &lt;SPAN class=code&gt;T&lt;/SPAN&gt; as &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt;, but cannot figure out what &lt;SPAN class=code&gt;R&lt;/SPAN&gt; is because &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt; does not have a property &lt;SPAN class=code&gt;FristName&lt;/SPAN&gt;. Therefore type inference fails, and therefore overload resolution fails, and therefore our heuristic takes over and gives the error that type inference failed on &lt;SPAN class=code&gt;Select&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;I think you would agree that the user does not think of the error in this program as being a failure of overload resolution or type inference; they think that the failure is that there's a typo in one clause of the query. Wes did quite a bit of work on the heuristics to go back one step further, and report why type inference failed; because the body of the lambda could not be successfully bound.&lt;/P&gt;
&lt;P mce_keep="true"&gt;So that's one change to type inference between C# 2.0 and C# 3.0, but I seem to have gotten ahead of myself somewhat. Next time we'll take a closer look at how the mechanism of type inference works in C# 2.0.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8611835" 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/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx">Type Inference</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category></item><item><title>Future Breaking Changes, Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2007/08/31/future-breaking-changes-part-two.aspx</link><pubDate>Fri, 31 Aug 2007 17:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4649198</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/4649198.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=4649198</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/08/30/future-breaking-changes-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/08/30/future-breaking-changes-part-one.aspx"&gt;Last time&lt;/A&gt; I mentioned that one of the subtleties of programming language design is weighing the benefit of adding a feature against the pain it will cause you in the future. This is a specific&amp;nbsp;subset of a more general set of problems. Languages run into the same problem that other large, multiply-versioned software products run into; if you have n existing features and want to add m new features, then you have at least m x n possible interactions to consider. In an ideal world the features would all be &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2005/10/28/483905.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/10/28/483905.aspx"&gt;orthogonal&lt;/A&gt; to each other, but in reality of course new features modify the behaviour of existing features. &lt;/P&gt;
&lt;P&gt;Just as a random example, what on earth do &lt;A class="" href="http://blogs.msdn.com/wesdyer/archive/2007/05/23/in-case-you-haven-t-heard.aspx" mce_href="http://blogs.msdn.com/wesdyer/archive/2007/05/23/in-case-you-haven-t-heard.aspx"&gt;partial methods&lt;/A&gt; have to do with &lt;A class="" href="http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees" mce_href="http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees"&gt;expression trees&lt;/A&gt;? Both are new features for C# 3.0, but other than that, they seem to have nothing to do with each other. But what happens when you have an expression tree lambda which contains &lt;EM&gt;a call to a partial method which is going to be removed&lt;/EM&gt;? This interaction has to be carefully defined. &lt;EM&gt;Every interaction between every feature has to be carefully defined&lt;/EM&gt;, and the larger the area of the feature interaction is, the more likely it is that there will be unfortunate consequences of this nonorthogonality, such as breaking changes.&lt;/P&gt;
&lt;P&gt;I said last time that implicitly typed&amp;nbsp;lambdas are just such a feature -- big surface area of nonorthogonal interactions which will lead to future breaking changes. I'd like to explore that in more detail, because it might not be immediately obvious why that is the case.&lt;/P&gt;
&lt;P&gt;The rule for determining whether an &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx"&gt;implicitly typed lambda&lt;/A&gt; is convertible to a given delegate type is (somewhat simplified) “If possible, infer the return type and the types of the lambda parameters from the delegate type. Try to&amp;nbsp;bind the lambda with those types. If the inference and&amp;nbsp;binding succeeds&amp;nbsp;with no errors&amp;nbsp;then the lambda expression is convertible to that delegate type.” &lt;/P&gt;
&lt;P&gt;For example, if we had a lambda expression like &lt;SPAN class=code&gt;x=&amp;gt;x - 123.4&lt;/SPAN&gt;, that would be convertible to &lt;SPAN class=code&gt;&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2006/06/21/641831.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2006/06/21/641831.aspx"&gt;Func&amp;lt;double, double&amp;gt;&lt;/A&gt;&lt;/SPAN&gt; but not to &lt;SPAN class=code&gt;Func&amp;lt;string, double&amp;gt;&lt;/SPAN&gt; (because the subtraction cannot be legally bound) or &lt;SPAN class=code&gt;Func&amp;lt;double, int&amp;gt;&lt;/SPAN&gt; (because&amp;nbsp;the conversion to the return type cannot be bound).&lt;/P&gt;
&lt;P&gt;Notice how the overlap between this new feature – implicitly typed lambda convertibility to a delegate type – overlaps with&amp;nbsp;almost every other feature&amp;nbsp;in the entire C# language. Consider the impact of this design decision on the potential for breaking changes in the future. &lt;EM&gt;Every single time we make a change to the rules for how the body of a method is bound, we are potentially changing whether a given lambda expression is convertible to a given type.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Now, is that really so bad? Generally when we make changes to the method body binding rules, we do so in as non-breaking a manner as possible. We should never be making an existing lambda that &lt;EM&gt;does&lt;/EM&gt; convert suddenly &lt;EM&gt;stop&lt;/EM&gt; converting, because then we would also be breaking compilation of the equivalent &lt;EM&gt;nominal&lt;/EM&gt; method body. Really we should only be causing presently-erroneous code to suddenly start being non-erroneous, and as we’ve already discussed, that’s not a breaking change.&lt;/P&gt;
&lt;P&gt;Or is it?&lt;/P&gt;
&lt;P&gt;Actually, now in a lot of cases it could be.&lt;/P&gt;
&lt;P&gt;Consider a silly example. Suppose we decide that in some hypothetical C# 4.0(‡) language it should be legal to subtract a double from a string. That’s not entirely farfetched – that’s perfectly legal in JScript. You just convert the&amp;nbsp;string to a number&amp;nbsp;and subtract. We might reason that this new feature is not a breaking change, because no program that ever&amp;nbsp;subtracted a double from a string&amp;nbsp;ever compiled before. But it &lt;EM&gt;is&lt;/EM&gt; a breaking change, because now &lt;EM&gt;this&lt;/EM&gt; program stops compiling:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;using System;&lt;BR&gt;class Program {&lt;BR&gt;&amp;nbsp; void M(Func&amp;lt;double, int&amp;gt; f){}&lt;BR&gt;&amp;nbsp; void M(Func&amp;lt;string, double&amp;gt; f){}&lt;BR&gt;&amp;nbsp; void M(Func&amp;lt;double, double&amp;gt; f){}&lt;BR&gt;&amp;nbsp; static void Main() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; M(x=&amp;gt;x-123.4);&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Before the change, the program unambiguously chooses the third overload. But with our change to addition semantics, now the second and third overloads would both work. Neither would be clearly better than the other. The compiler would then give an ambiguity error. Thus, this is a breaking change. &lt;/P&gt;
&lt;P&gt;It gets even worse; with some cleverness we could come up with more subtle breaking changes, where the compiler would not produce an error but instead would choose a &lt;EM&gt;different&lt;/EM&gt; overload than before. At least a program which fails to compile calls attention to the problem; recompiling and having the behaviour change subtly might go unnoticed for a long time.&lt;/P&gt;
&lt;P&gt;This is a general problem with overload resolution: it depends upon conversion semantics. If we make the conversion semantics more strict then it is possible to go from having exactly one overload which works to zero, which is a breaking change. If we make the conversion semantics less strict then it is possible to go from having exactly one overload which works to two, which is also (usually) a breaking change.&lt;/P&gt;
&lt;P&gt;Since lambda convertibility depends on every other language rule for binding an expression, any change to &lt;EM&gt;any&lt;/EM&gt; of those rules is a potential change in convertibility, and hence a potential breaking change for overload resolution. Now, hopefully few real-world codebases will end up in the above situation, where a method is overloaded solely on a bunch of different delegate types, but still, I worry. We think implicitly typed lambdas are worth it, but this was a tough call that we agonized over for a long time.&lt;/P&gt;
&lt;P&gt;Next time on FAIC: More on subtle language design issues involving breaking changes. Have a pleasant Labour Day weekend, Canadian and American readers!&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;(‡) I call out that this is the &lt;EM&gt;hypothetical&lt;/EM&gt; C# 4.0 compiler because of course I do not discuss the feature set of unannounced and non-existing products on public blogs. &lt;BR&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4649198" 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/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category></item><item><title>Lambda Expressions vs. Anonymous Methods, Part Five</title><link>http://blogs.msdn.com/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx</link><pubDate>Wed, 28 Mar 2007 17:45:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1956384</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/1956384.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=1956384</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx"&gt;Last time&lt;/A&gt; I demonstrated that the compiler could have to do an exponential number of bindings in order to determine whether there was a unique best overload resolution for a function call that takes a lambda. Some of you may have wondered whether we simply were not being clever enough in the compiler. Perhaps there is some way to optimize this problem so that the unique solution is found in less than exponential time. &lt;/P&gt;
&lt;P&gt;As it turns out, the question of whether there is a clever way to do this in C# 3.0&amp;nbsp;is equivalent to solving the most famous unsolved problem in computer science. That is a problem which has stumped generations of the finest minds in academia,&amp;nbsp;and is widely believed to be unsolvable, so I don't feel &lt;EM&gt;particularly&lt;/EM&gt; bad about not solving this one myself. &lt;/P&gt;
&lt;P&gt;Consider the following &lt;EM&gt;slight&lt;/EM&gt; revision of the set of overloads I sketched out last time:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;class MainClass&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class T{}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class F{}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate void DT(T t);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate void DF(F f);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void M(DT dt)&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; System.Console.WriteLine("true");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; dt(new T());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void M(DF df)&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; System.Console.WriteLine("false");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; df(new F());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static T Or(T a1, T a2){return new T();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static T Or(T a1, F a2){return new T();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static T Or(F a1, T a2){return new T();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static F Or(F a1, F a2){return new F();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static T And(T a1, T a2){return new T();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static F And(T a1, F a2){return new F();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static F And(F a1, T a2){return new F();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static F And(F a1, F a2){return new F();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static F Not(T a){return new F();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static T Not(F a){return new T();}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void MustBeT(T t){}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Introduce enough variables and then&amp;nbsp;encode any Boolean predicate:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;eg,&amp;nbsp;here we encode (!x3) &amp;amp; ((!x1) &amp;amp; ((x1 | x2) &amp;amp; (x2 | x3)))&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; M(x1=&amp;gt;M(x2=&amp;gt;M(x3=&amp;gt;MustBeT(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; And(&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; Not(x3),&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; And(&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; Not(x1),&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; And(&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; Or(x1, x2),&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Or(x2, x3))))))));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This expression&amp;nbsp;&lt;I&gt;makes the compiler solve the &lt;A class="" href="http://en.wikipedia.org/wiki/Boolean_satisfiability_problem" mce_href="http://en.wikipedia.org/wiki/Boolean_satisfiability_problem"&gt;Boolean satisfiability problem&lt;/A&gt;&lt;/I&gt; (aka "SAT"). If SAT has a unique solution then the program compiles and produces the unique solution. If it has more than one solution then compilation fails with an ambiguity error. If it has no solution then the program fails with the error that &lt;SPAN class=code&gt;MustBeT&lt;/SPAN&gt; has an &lt;SPAN class=code&gt;F&lt;/SPAN&gt; argument. But no matter how you slice it, the compiler must solve SAT. &lt;/P&gt;
&lt;P&gt;Determining whether a given predicate has a set of valuations for its variables which make it true is an &lt;A class="" href="http://en.wikipedia.org/wiki/NP-complete" mce_href="http://en.wikipedia.org/wiki/NP-complete"&gt;NP-complete&lt;/A&gt; problem; actually &lt;EM&gt;finding&lt;/EM&gt; the set of valuations is an &lt;A class="" href="http://en.wikipedia.org/wiki/NP-hard" mce_href="http://en.wikipedia.org/wiki/NP-hard"&gt;NP-hard&lt;/A&gt; problem. Therefore, &lt;EM&gt;overload resolution in C# 3.0&amp;nbsp;is at the very least NP-hard&lt;/EM&gt;. There is no known polynomial-time algorithm for any NP-complete or NP-hard problem and it is widely believed that there is none to be found, though that conjecture has yet to be proven. So our dream of fast lambda type analysis in C# 3.0&amp;nbsp;is almost certainly doomed, at least as long as we have the current rules for overload resolution. &lt;/P&gt;
&lt;P&gt;Does this really matter in practice? As I mentioned last time, hopefully not. Other languages also have this issue. When I ran an early&amp;nbsp;draft of this post&amp;nbsp;past him, &lt;A class="" href="http://research.microsoft.com/~emeijer/" mce_href="http://research.microsoft.com/~emeijer/"&gt;Erik Meijer&lt;/A&gt; immeditely pointed out that the &lt;A class="" href="http://en.wikipedia.org/wiki/ML_programming_language" mce_href="http://en.wikipedia.org/wiki/ML_programming_language"&gt;ML&lt;/A&gt; type inference system has &lt;A class="" href="http://portal.acm.org/citation.cfm?id=96748&amp;amp;coll=portal&amp;amp;dl=ACM" mce_href="http://portal.acm.org/citation.cfm?id=96748&amp;amp;coll=portal&amp;amp;dl=ACM"&gt;similar worst cases&lt;/A&gt;, and the &lt;A class="" href="http://en.wikipedia.org/wiki/Haskell_%28programming_language%29" mce_href="http://en.wikipedia.org/wiki/Haskell_%28programming_language%29"&gt;Haskell&lt;/A&gt; type inference system is even worse. Apparently in Haskell you can encode a Turing machine into the type system and make the compiler run it! In practice these sorts of problems do not arise in real-world code in any of these languages, so I am not too worried about it for C# 3.0. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1956384" 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/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/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category></item><item><title>Lambda Expressions vs. Anonymous Methods, Part Four</title><link>http://blogs.msdn.com/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx</link><pubDate>Tue, 27 Mar 2007 02:05:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1955901</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/1955901.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=1955901</wfw:commentRss><description>&lt;DIV class=mine&gt;Hey all, sorry for the long time between posts; I have been crazy busy &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/01/30/free-food-and-meet-the-compiler-guy-and-win-an-xbox-360.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/01/30/free-food-and-meet-the-compiler-guy-and-win-an-xbox-360.aspx"&gt;recruiting&lt;/A&gt;, interviewing, fixing bugs, making performance improvements and implementing last-minute changes to the language and expression tree library. The last few posts about lambda binding yielded many interesting comments which I hope to address over the next month or so. 
&lt;P&gt;Before that though -- back when I &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx"&gt;started&lt;/A&gt; this series of posts I noted that lambda expressions have an interesting property. Namely, &lt;EM&gt;the semantic analysis of the lambda body may depend upon what type the lambda is being converted to&lt;/EM&gt;. This seemingly trivial fact has an important impact upon the compiler performance during analysis. At long last, let me demonstrate the impact this fact has. &lt;/P&gt;
&lt;P&gt;Consider the following set of overloads: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;int M(Func&amp;lt;int, int&amp;gt; f){ /* whatever ... */ }&lt;BR&gt;string M(Func&amp;lt;string, string&amp;gt; f){ /* whatever ... */ }&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Now suppose we have a call with a lambda argument: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;M(x=&amp;gt;x.ToUpper()); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;During overload resolution we make a list of all the potential overloads and we see which are applicable. That is, which overloads have the property that all of the arguments are convertible to the types of their corresponding formal parameters. Then of all the applicable methods, we pick the best match if there happens to be more than one. &lt;/P&gt;
&lt;P&gt;Therefore we must try this binding two ways. We try it as though it were &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;M((int x)=&amp;gt;x.ToUpper()); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;and &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;M((string x)=&amp;gt;x.ToUpper()); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;The former produces an error while binding the body because there is no &lt;SPAN class=code&gt;ToUpper&lt;/SPAN&gt; method on &lt;SPAN class=code&gt;int&lt;/SPAN&gt;. The latter binds the body correctly and the return type matches the expected return type, so this one succeeds. The first &lt;SPAN class=code&gt;M&lt;/SPAN&gt; is not applicable so it is discarded, the second one is applicable, so it is chosen, all is good in the world. &lt;/P&gt;
&lt;P&gt;Or is it? &lt;/P&gt;
&lt;P&gt;What if we did something crazy like this? &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;M(x1=&amp;gt;M(x2=&amp;gt;x1.ToLower() + x2.ToUpper()); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;OK, so now what do we do? We try to do overload resolution on the outer call. Again, we must try both &lt;SPAN class=code&gt;int&lt;/SPAN&gt; and &lt;SPAN class=code&gt;string&lt;/SPAN&gt; as candidates for &lt;SPAN class=code&gt;x1&lt;/SPAN&gt;. But then when we get to the outer body, we are faced with the same problem for &lt;SPAN class=code&gt;x2&lt;/SPAN&gt;. &lt;/P&gt;
&lt;P&gt;We have to try all four possibilities for &lt;SPAN class=code&gt;{x1, x2}&lt;/SPAN&gt; (that is, &lt;SPAN class=code&gt;{int, int}&lt;/SPAN&gt;, &lt;SPAN class=code&gt;{int, string}&lt;/SPAN&gt;, &lt;SPAN class=code&gt;{string, int}&lt;/SPAN&gt; and &lt;SPAN class=code&gt;{string, string}&lt;/SPAN&gt;) in order to determine how many of them work, and of the ones that work, which one is the best. In this particular example "both are string" is the only one that works. (We could with a little more cleverness come up with examples where there were multiple possible matches that worked.) &lt;/P&gt;
&lt;P&gt;So perhaps you see where this is going. If there are m overloads that are nested in this manner n deep, then the compiler must try m&lt;SUP&gt;n&lt;/SUP&gt; possibilities in order to determine which is the unique best one. If it's 2&lt;SUP&gt;2&lt;/SUP&gt; = 4, that's not a big deal. If we triple each and go to 6&lt;SUP&gt;6&lt;/SUP&gt; = 46656, that's rather a lot of binding to do, and it takes up rather a lot of time and memory. &lt;/P&gt;
&lt;P&gt;Does this seem like a contrived example? Unfortunately, it is not. In the original prototype of C# 3.0, nested &lt;SPAN class=code&gt;from&lt;/SPAN&gt; clauses in queries were translated into nested lambdas in &lt;EM&gt;exactly&lt;/EM&gt; this manner, and most of the translation methods have at least two overloads, some have many more. We were easily getting into situations where simple queries could involve &lt;I&gt;millions&lt;/I&gt; of body bindings. Fortunately we realized the problem in time; my colleague &lt;A class="" href="http://blogs.msdn.com/wesdyer/" mce_href="http://blogs.msdn.com/wesdyer/"&gt;Wes&lt;/A&gt; came up with an alternative translation strategy which does not generate nested lambdas so aggressively and we therefore avoid this problem in the common case. You can still get into it yourself though; please do not.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Next time I'll create a truly contrived (and rather hilarious) example which demonstrates just how bad things can get and just how hard you can make the compiler work to do overload resolution on lambdas.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1955901" 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/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category></item><item><title>Odious ambiguous overloads, part one</title><link>http://blogs.msdn.com/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx</link><pubDate>Wed, 05 Apr 2006 18:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:569085</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>9</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/569085.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=569085</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;As you might have gathered, a lot of the decisions we have to make day-to-day here involve potential breaking changes on odd edge cases. Here's another one. &lt;/P&gt;
&lt;P&gt;Consider the following terrible but legal code:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface I1&amp;lt;U&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(U i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(int i);&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;My&amp;nbsp;intense pain begins when the user writes:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C1 : I1&amp;lt;int&amp;gt; {&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;In the early version of the C# specification it was actually illegal to have an ambiguity like this, but the spec was changed so that when doing overload resolution on a call to &lt;SPAN class=code&gt;M&lt;/SPAN&gt; we can choose one, according to section 14.4.2.2:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;If one [argument type] is non-generic, but the other is generic, then the non-generic is better. &lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;But still, as you will soon see, we're in a world of hurt for another reason, namely that&amp;nbsp;this class must now implement both &lt;SPAN class=code&gt;M(int i)&lt;/SPAN&gt; and, uh, &lt;SPAN class=code&gt;M(int i)&lt;/SPAN&gt;.&amp;nbsp;Fortunately, a nonexplicit implementation binds to both methods, so this works just fine:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C1 : I1&amp;lt;int&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void M(int i) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("class " + i); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The method implements both versions of &lt;SPAN class=code&gt;M&lt;/SPAN&gt; and the contract is satisfied.&amp;nbsp; But we have problems if we try to do an explicit interface implementation:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public class C2 : I1&amp;lt;int&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void I1&amp;lt;int&amp;gt;.M(int i) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("explicit " + i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Does this explicitly implement both members of &lt;SPAN class=code&gt;I1&lt;/SPAN&gt;?&amp;nbsp; Or just one?&amp;nbsp; If so, which one?&lt;/P&gt;
&lt;P&gt;In the current compiler this code produces a terrible, terrible error:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;error CS0535: 'C2' does not implement interface member 'I1&amp;lt;int&amp;gt;.M(int)'&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Is that so?&amp;nbsp; It sure looks like it implements it!&lt;/P&gt;
&lt;P&gt;What happens when we have both an explicit implementation and a class implementation?&amp;nbsp; &lt;STRONG&gt;The spec does not actually say what to do.&lt;/STRONG&gt; It turns out that we end up in a situation where runtime behaviour depends on &lt;STRONG&gt;source code order&lt;/STRONG&gt; of the interface! Check this out:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;public interface I1&amp;lt;U&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(U i); // generic first&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(int i);&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;public interface I2&amp;lt;U&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(int i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void M(U i); // generic second&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;public class C3: I1&amp;lt;int&amp;gt;, I2&amp;lt;int&amp;gt; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void I1&amp;lt;int&amp;gt;.M(int i) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("c3 explicit I1 " + i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void I2&amp;lt;int&amp;gt;.M(int i) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("c3 explicit I2 " + i);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void M(int i) { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("c3 class " + i); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;class Test {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C3 c3 = new C3();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; I1&amp;lt;int&amp;gt; i1_c3 = c3;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; I2&amp;lt;int&amp;gt; i2_c3 = c3;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i1_c3.M(101);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i2_c3.M(102);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;What happens here is that the explicit interface implementation mappings in the class match the methods in the interfaces in a first-come-first-served manner:&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;void I1&amp;lt;int&amp;gt;.M(U)&lt;/SPAN&gt; maps to explicit implementation &lt;SPAN class=code&gt;void I1&amp;lt;int&amp;gt;.M(int i)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=code&gt;void I1&amp;lt;int&amp;gt;.M(int)&lt;/SPAN&gt; maps to implicit implementation &lt;SPAN class=code&gt;public void M(int i)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=code&gt;void I2&amp;lt;int&amp;gt;.M(int)&lt;/SPAN&gt; maps to explicit implementation &lt;SPAN class=code&gt;void I2&amp;lt;int&amp;gt;.M(int i)&lt;/SPAN&gt;&lt;BR&gt;&lt;SPAN class=code&gt;void I2&amp;lt;int&amp;gt;.M(U)&lt;/SPAN&gt; maps to implicit implementation &lt;SPAN class=code&gt;public void M(int i)&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Then (because of the aforementioned section 14.4.2.2) when we see&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i1_c3.M(101);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i2_c3.M(102);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;we prefer the typed-as-int versions to the generic substitution versions, so this program calls the two non-generic versions and produces the output:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;c3 class 101&lt;BR&gt;c3 explicit I2 102&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;And as you'd expect,&amp;nbsp;if we force the compiler to pick the generic versions then we get similar behaviour:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static void Main() {&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;C3 c3 = new C3();&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Thunk1&amp;lt;int&amp;gt;(c3,103);&lt;BR&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;Thunk2&amp;lt;int&amp;gt;(c3, 104);&lt;BR&gt;}&lt;BR&gt;static void Thunk1&amp;lt;U&amp;gt;(I1&amp;lt;U&amp;gt; i1, U u) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i1.M(u);&lt;BR&gt;}&lt;BR&gt;static void Thunk2&amp;lt;U&amp;gt;(I2&amp;lt;U&amp;gt; i2, U u) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; i2.M(u);&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;The binding of the overload resolution in the thunk bodies happens before the substitution of the type parameters, so these always bind to the generic versions of the methods. As you would expect from the mappings above, this outputs&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;c3 explicit I1 103&lt;BR&gt;c3 class 104&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Again, this shows that source code order has an unfortunate semantic import.&lt;/P&gt;
&lt;P&gt;Given this unfortunate situation -- no spec guidance and an existing implementation that behaves strangely -- what would you do? (Of course "do nothing" is an option.) I'm interested to hear your ideas, and I'll describe what we actually did next time.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=569085" 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/Overload+Resolution/default.aspx">Overload Resolution</category></item></channel></rss>