<?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 : Type Inference</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx</link><description>Tags: Type Inference</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>76</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>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>Method Type Inference Changes, Part Zero</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/28/method-type-inference-changes-part-zero.aspx</link><pubDate>Wed, 28 May 2008 18:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8556674</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/8556674.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=8556674</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Back in November I wrote a bit about a &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx"&gt;corner case in method type inference&lt;/A&gt; which does not work as expected or as specified in C# 3.0. A number of people made blog comments, sent me mail, and entered "Connect" issues with additional problems and ideas for how we could improve this algorithm. (Particular thanks to nikov for his many fascinating and detailed Connect reports.) As a result, as soon as I had time I embarked upon a detailed review of the method type inference specification and the implementation. &lt;/P&gt;
&lt;P&gt;The good news is that this resulted in a complete overhaul of both the implementation and the specification; they are now consistent with each other and to the best of my knowledge, correct. Furthermore, the principle concern of commenters on my earlier article has been dealt with: return type inference from a method group to the return type of a delegate type will be legal, but only when the delegate type's input parameters are all completely known. This eliminates the "chicken and egg" problem I discussed in November, whereby overload resolution on the method group must consume the very same unfixed formal parameter types that it is attempting to infer.&lt;/P&gt;
&lt;P&gt;The bad news is that these changes to the implementation&amp;nbsp;will not make it in to the service release of C# 3.0; they will have to wait for a later revision of the compiler. (It is not yet clear to me whether or not the changes to the specification will make it into the next edition of the published specification.)&lt;/P&gt;
&lt;P&gt;This is one of the most complex areas of the specification and implementation; I'd like to spend some time in this blog going over the specification in detail and explaining where we got things subtly wrong, and how we intend to fix it.&lt;/P&gt;
&lt;P&gt;In this series I want to hit on the following points:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;What did method type inference look like in C# 2.0? Why was it inadequate for LINQ?&lt;/LI&gt;
&lt;LI&gt;How did we attempt to modify and ultimately rewrite the specification for C# 3.0?&lt;/LI&gt;
&lt;LI&gt;Where did we go subtly wrong in the specification and the implementation?&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Next time, we'll get started with a look back at C# 2.0.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8556674" 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></item><item><title>C# 3.0 Return Type Inference Does Not Work On Method Groups</title><link>http://blogs.msdn.com/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx</link><pubDate>Mon, 05 Nov 2007 21:48:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5914522</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>17</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/5914522.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=5914522</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Thanks all for your excellent feedback on my variance series. I am still reading and digesting the feedback and I shall take it to the language design committee later this month.&lt;/P&gt;
&lt;P&gt;Returning to less hypothetical but equally complicated&amp;nbsp;issues, today, what I thought would be a rather obscure issue with C# 3.0 type inference which multiple people have reported to me since the last beta. Perhaps it is not as obscure as I thought! &lt;/P&gt;
&lt;P&gt;Consider this (contrived, but simplified from real code) example where we want to see if a collection of customers has every member from London or not. The LINQ-to-Objects library has an &lt;SPAN class=code&gt;All&lt;/SPAN&gt; extension method sequence operator which returns &lt;SPAN class=code&gt;true&lt;/SPAN&gt; if a predicate is true of all members of a collection, so we can use that:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static string GetCity(Customer c)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; return c.City;&lt;BR&gt;}&lt;BR&gt;static bool IsLondon(string s)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp; return s == "London";&lt;BR&gt;}&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This works just fine:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var cities = customers.Select(c=&amp;gt;GetCity(c));&lt;BR&gt;bool allLondon = cities.All(s=&amp;gt;IsLondon(s));&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Now, assuming that this is LINQ-to-Objects and those lambdas are going to be turned into delegates, why do we need the lambdas at all? We can just turn the method groups into delegates directly. This works just fine too:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var cities = customers.Select(c=&amp;gt;GetCity(c));&lt;BR&gt;bool allLondon = cities.All(IsLondon);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;But this does not work:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var cities = customers.Select(GetCity); // Inference error&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;That fails with a type inference error stating that the type arguments for &lt;SPAN class=code&gt;Select&lt;/SPAN&gt; could not be determined. If you supply them explicitly, everything works:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;var cities = customers.Select&amp;lt;Customer, string&amp;gt;(GetCity); // No problem.&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Why does this fail on the &lt;SPAN class=code&gt;Select&lt;/SPAN&gt; but not on the &lt;SPAN class=code&gt;All&lt;/SPAN&gt;? And is that the correct behaviour according to the specification?&lt;/P&gt;
&lt;P&gt;Unfortunately, the published 3.0 specification states that this should work for the &lt;SPAN class=code&gt;Select&lt;/SPAN&gt;. I did not realize that the implementation was out of line with the specification until the spec was already on the web, and upon review, we realized that &lt;STRONG&gt;the implementation was correct and the specification was wrong&lt;/STRONG&gt;. (We will batch up the specification errors we’ve discovered so far and fix them all at once in a future revision; we do not want to fix specification errors piecemeal.)&lt;/P&gt;
&lt;P&gt;Let’s go through the process of type inference and we’ll see where things go wrong. The definition of &lt;SPAN class=code&gt;Select&lt;/SPAN&gt; is:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static IEnumerable&amp;lt;R&amp;gt; Select&amp;lt;C, R&amp;gt;(this IEnumerable&amp;lt;C&amp;gt; collection, Func&amp;lt;C, R&amp;gt; projection) { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;When we see&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;customers.Select(c=&amp;gt;GetCity(c));&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;the type inference process reasons as follows. From the first argument we unambiguously deduce that &lt;SPAN class=code&gt;C&lt;/SPAN&gt; is &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt;. That means that the second argument must be a &lt;SPAN class=code&gt;Func&amp;lt;Customer, R&amp;gt;&lt;/SPAN&gt;, but we do not know what &lt;SPAN class=code&gt;R&lt;/SPAN&gt; is. We then analyze the lambda as if it were written &lt;SPAN class=code&gt;(Customer c)=&amp;gt;{ return GetCity(c); }&lt;/SPAN&gt;. We do overload resolution on &lt;SPAN class=code&gt;GetCity(c)&lt;/SPAN&gt; and make an exact match to the &lt;SPAN class=code&gt;string GetCity(Customer)&lt;/SPAN&gt; method. We therefore deduce that the lambda returns a &lt;SPAN class=code&gt;string&lt;/SPAN&gt;, and therefore deduce that &lt;SPAN class=code&gt;R&lt;/SPAN&gt; is &lt;SPAN class=code&gt;string&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;At this point we have now deduced both &lt;SPAN class=code&gt;C&lt;/SPAN&gt; and &lt;SPAN class=code&gt;R&lt;/SPAN&gt;. We verify that the arguments are all compatible with the deduced types of the formal parameters and life is good.&lt;/P&gt;
&lt;P&gt;Now consider what happens when we see:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;customers.Select(GetCity);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;This time, type inference goes like this: again, we unambiguously deduce that &lt;SPAN class=code&gt;C&lt;/SPAN&gt; is &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt;. The second argument is a &lt;SPAN class=code&gt;Func&amp;lt;Customer, R&amp;gt;&lt;/SPAN&gt;, but we do not know what &lt;SPAN class=code&gt;R&lt;/SPAN&gt; is. We have a&amp;nbsp;method group as the second argument. In order to determine what method the method group refers to, we must do overload resolution on it. But… we do not have any arguments! How can we do overload resolution on &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt; if we do not know what the arguments to the call are? Sure, in this case there is only one method in the method group and it is not generic, so we could just pick it. But we ought to solve the general problem here.&lt;/P&gt;
&lt;P&gt;Now, you might point out that we manage to do overload resolution correctly for this case:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Func&amp;lt;Customer, string&amp;gt; f = GetCity;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Overload resolution works just fine there even though we have no arguments to &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt;. In that case we take the signature of the delegate and use the type of each parameter in the delegate signature to do overload resolution. That is, we do it as though we were doing overload resolution on &lt;SPAN class=code&gt;GetCity(default(Customer))&lt;/SPAN&gt;. That is then enough information to do overload resolution on &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;I seem to be digging myself in deeper. Why don’t we do the same thing in the type inference case above?&lt;/P&gt;
&lt;P&gt;Because I skipped a step in overload resolution. What if we need to do type inference on &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt;?&lt;/P&gt;
&lt;P&gt;Suppose instead of the simple example above we had something like&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;S GetCity&amp;lt;X, S&amp;gt;(X x) { …&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Now consider what happens when we have&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;Func&amp;lt;Customer, string&amp;gt; f = GetCity;&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;In this case before we do overload resolution we first do type inference FROM &lt;SPAN class=code&gt;Func&amp;lt;Customer, string&amp;gt;&lt;/SPAN&gt; TO &lt;SPAN class=code&gt;GetCity&amp;lt;X, S&amp;gt;&lt;/SPAN&gt; and deduce that &lt;SPAN class=code&gt;X&lt;/SPAN&gt; and &lt;SPAN class=code&gt;S&lt;/SPAN&gt; are &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt; and &lt;SPAN class=code&gt;string&lt;/SPAN&gt;. Then overload resolution proceeds normally.&lt;/P&gt;
&lt;P&gt;Am I still digging myself deeper? No. Perhaps now you see the problem. Suppose we had a generic &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt; and we said:&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;customers.Select(GetCity);&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;We get as far as deducing that we have &lt;SPAN class=code&gt;Func&amp;lt;Customer, R&amp;gt;&lt;/SPAN&gt;, and now we are in a hideous bind. In order to determine &lt;SPAN class=code&gt;R&lt;/SPAN&gt; we need to determine the return type of &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt;. To determine the return type of &lt;SPAN class=code&gt;GetCity&lt;/SPAN&gt; we need to do overload resolution on the&amp;nbsp;method group. To do overload resolution on the method group, we need to do type inference on the method group. To do type inference on it we need to know what delegate type it is going to. It is going to &lt;SPAN class=code&gt;Func&amp;lt;Customer, R&amp;gt;&lt;/SPAN&gt;. But &lt;SPAN class=code&gt;R&lt;/SPAN&gt; is what we are trying to figure out! &lt;STRONG&gt;We do not yet know the delegate type that it is going to, so overload resolution is in general impossible&lt;/STRONG&gt;. This is a circle that will stay unbroken (by and by Lord, by and by.)&lt;/P&gt;
&lt;P&gt;It does not actually make any sense to try to do overload resolution in the general type inference scenario. We could have come up with a weaker form of overload resolution that worked in an environment where type inference might not succeed, but that would then introduce a brand new and subtly incompatible set of overload resolution rules which would only come into effect in these obscure inference scenarios where one type inference triggers another. We want the language semantics to remain understandable and testable, and we’re pushing that edge pretty hard already with the new type inference features.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Therefore this scenario is illegal; you cannot do return type inference on a method group, only on a lambda. &lt;/STRONG&gt;The compiler can peer into the lambda and determine what type it &lt;EM&gt;would&lt;/EM&gt; return were all its arguments known, but the compiler cannot do that with a method group. There is simply less information available with a method group.&lt;/P&gt;
&lt;P&gt;Why then does the &lt;SPAN class=code&gt;All(IsLondon) case work?&lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;Because the signature of &lt;SPAN class=code&gt;All&lt;/SPAN&gt; is&lt;/P&gt;&lt;SPAN class=code&gt;
&lt;P&gt;static bool All&amp;lt;C&amp;gt;(this IEnumerable&amp;lt;C&amp;gt; collection, Func&amp;lt;C, bool&amp;gt; predicate) &lt;/P&gt;&lt;/SPAN&gt;
&lt;P&gt;By the type we need to do overload resolution on the method group the type of the second parameter is &lt;EM&gt;entirely&lt;/EM&gt; known. The rule that return type inference cannot be done on method groups does not apply because there is no return type inference necessary.&lt;/P&gt;
&lt;P&gt;[UPDATE: In the C# specification, an expression naming a method is called a "method group". Unfortunately, in the compiler source code they are called "member groups", and this gets me in the bad habit of using imprecise language. In the original version of this article I referred to "member groups" throughout; I've fixed those up. Sorry for any confusion.]&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5914522" 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></item><item><title>Lambda Expressions vs. Anonymous Methods, Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part-two.aspx</link><pubDate>Thu, 11 Jan 2007 23:40:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1451894</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/1451894.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=1451894</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;We interrupt the discussion of how the difference between lambda expression and anonymous method convertibility leads to potential performance problems in the compiler to answer a user question. &lt;/P&gt;
&lt;P&gt;Within hours of yesterday's post readers &lt;A href="http://blogs.msdn.com/oldnewthing" mce_href="http://blogs.msdn.com/oldnewthing"&gt;Raymond Chen&lt;/A&gt; and &lt;A href="http://musingmarc.blogspot.com/" mce_href="http://musingmarc.blogspot.com/"&gt;Marc Brooks&lt;/A&gt; both asked me the same question. &lt;B&gt;How do lambdas and anonymous methods interact with implicitly typed local variables?&lt;/B&gt; &lt;/P&gt;
&lt;P&gt;Recall that C# 3.0 will support implicitly typed local variables. This: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;var d = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;(); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;is a syntactic sugar for &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt; d = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;(); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Again, I wish to emphasize that &lt;A href="http://blogs.msdn.com/ericlippert/archive/2005/09/27/474462.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/09/27/474462.aspx"&gt;C# 3.0 is still statically typed, honest!&lt;/A&gt; The &lt;SPAN class=code&gt;var&lt;/SPAN&gt; keyword does not have the semantics of the JScript &lt;SPAN class=code&gt;var&lt;/SPAN&gt; or VBScript's &lt;SPAN class=code&gt;Variant&lt;/SPAN&gt; or any such thing. It simply means "the variable is the type of the right side of the declaration". We are committed to keeping C# 3.0 a &lt;A href="http://blogs.msdn.com/wesdyer/archive/2006/12/20/types-of-confusion.aspx" mce_href="http://blogs.msdn.com/wesdyer/archive/2006/12/20/types-of-confusion.aspx"&gt;statically typed&lt;/A&gt; language. &lt;/P&gt;
&lt;P&gt;You will note that a key requirement there is that the right hand side actually has a type. Furthermore, it cannot be the null type or the void type, obviously. So then what should this do? &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;var f = i=&amp;gt;F(i); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Clearly this cannot be legal; since as I discussed &lt;A 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;yesterday&lt;/A&gt; the type of the formal parameter is determined from the target type, and we are trying to determine the target type, we have a chicken-and-egg problem where there is not enough information to determine the type. &lt;/P&gt;
&lt;P&gt;What about this? &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;var f = (int i)=&amp;gt;i; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Here we know the type of the parameter, we can infer the type of the return easily enough, it's the same type as the parameter! We're set, right? &lt;/P&gt;
&lt;P&gt;Not so fast. &lt;/P&gt;
&lt;P&gt;Consider the following type declarations: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;public delegate int D1(int i);&lt;BR&gt;public delegate int D2(int i);&lt;BR&gt;public delegate int D3&amp;lt;A&amp;gt;(A a);&lt;BR&gt;public delegate R D4&amp;lt;A, R&amp;gt;(A a);&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;If the &lt;SPAN class=code&gt;var&lt;/SPAN&gt; were replaced by &lt;SPAN class=code&gt;D1&lt;/SPAN&gt;, &lt;SPAN class=code&gt;D2&lt;/SPAN&gt;, &lt;SPAN class=code&gt;D3&amp;lt;int&amp;gt;&lt;/SPAN&gt;, &lt;SPAN class=code&gt;D4&amp;lt;int, int&amp;gt;&lt;/SPAN&gt;, or for that matter, &lt;SPAN class=code&gt;D4&amp;lt;int, double&amp;gt;&lt;/SPAN&gt; or &lt;SPAN class=code&gt;D4&amp;lt;int, object&amp;gt;&lt;/SPAN&gt;, we'd have a legal program. So what &lt;EM&gt;is&lt;/EM&gt; the type of the right hand side? How can we choose which of these is the best?&lt;/P&gt;
&lt;P&gt;We can't. Delegate types are not even structurally equivalent; you can't even assign a variable of type &lt;SPAN class=code&gt;D1&lt;/SPAN&gt; to a variable of type &lt;SPAN class=code&gt;D2&lt;/SPAN&gt;. We would always potentially choose wrong.&lt;/P&gt;
&lt;P&gt;What this tells us is that it is more than just that the formal parameter types of an implicitly typed lambda expression flow from the target type. The type of the &lt;EM&gt;entire&lt;/EM&gt; lambda expression flows from the target type, and therefore, &lt;STRONG&gt;lambda expressions themselves must have no type&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P&gt;And in fact the C# 2.0 specification calls this out. Method group expressions and anonymous method expressions are &lt;EM&gt;typeless expressions&lt;/EM&gt; in C# 2.0, and lambda expressions join them in C# 3.0. Therefore it is illegal for them to appear "naked" on the right hand side of an implicit declaration.&lt;/P&gt;
&lt;P&gt;This is rather unfortunate because it makes it difficult to declare a variable of type "delegate which takes or returns an anonymous type". The whole point of the var feature in the first place is to make anonymous types work, and yet we seem to have a hole here. As it turns out, it is possible! Next time I'll describe a clever trick whereby we can use &lt;EM&gt;method type inference&lt;/EM&gt; to make variable type inference work correctly on lambdas which take anonymous types.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1451894" 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></item><item><title>A Face Made For Email, Part Three</title><link>http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx</link><pubDate>Fri, 17 Nov 2006 19:38:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1094663</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>14</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/1094663.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=1094663</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Yes, &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/04/06/108652.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2004/04/06/108652.aspx"&gt;it&lt;/A&gt; has happened &lt;A href="http://blogs.msdn.com/ericlippert/archive/2005/04/01/404642.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2005/04/01/404642.aspx"&gt;again&lt;/A&gt;.&lt;/A&gt; This time, our fabulous C# Community Program Manager &lt;A href="http://blogs.msdn.com/charlie" mce_href="http://blogs.msdn.com/charlie"&gt;Charlie Calvert&lt;/A&gt; was good enough to put together a little half-hour-long video of me talking about the scenarios which justify changes to the type inference algorithm for C# 3.0. We've already made some interesting changes which will make it into the beta version, and there likely will be further refinements to the algorithm as we see how it works. &lt;/P&gt;
&lt;P&gt;The video is &lt;A href="http://wm.microsoft.com/ms/msdn/visualcsharp/eric_lippert_2006_11/EricLippert01.wmv"&gt;here&lt;/A&gt;. &lt;/P&gt;
&lt;P&gt;I shall also likely be blogging about these algorithms over the next few weeks when I find time to turn my developer notes into blog posts. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1094663" 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/Type+Inference/default.aspx">Type Inference</category></item><item><title>Type inference woes, part four</title><link>http://blogs.msdn.com/ericlippert/archive/2006/07/18/type-inference-woes-part-four.aspx</link><pubDate>Tue, 18 Jul 2006 20:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:669993</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/669993.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=669993</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/ericlippert/archive/2006/05/30/610769.aspx"&gt;Last time in this series &lt;/A&gt;I discussed how we are probably going to identify a "best" type from a set of expressions. Clearly we need to solve this problem for features such as implicitly typed arrays. We are also considering extending this algorithm to affect type inference of generic methods. &lt;/P&gt;
&lt;P&gt;As always, the reason we're considering this is emminently practical; we try hard to not add new language semantics just for the heck of it, but rather in response to specific user problems. Before I get into the motivating problem, let me describe a simpler case that might look familiar: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;void M&amp;lt;T&amp;gt;(T t1, T t2){}&lt;BR&gt;...&lt;BR&gt;M(myShort, 0); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;In our currently shipped C# compiler, the type inference algorithm insists that all inferences be 100% completely consistent. &lt;SPAN class=code&gt;T &lt;/SPAN&gt;cannot be both &lt;SPAN class=code&gt;int&lt;/SPAN&gt; and &lt;SPAN class=code&gt;short&lt;/SPAN&gt;, so inference fails in this case. &lt;/P&gt;
&lt;P&gt;It might be kind of nice to say, you know what, the "best type" algorithm would tell us that &lt;SPAN class=code&gt;short&lt;/SPAN&gt; is best, so why don't we use it? &lt;/P&gt;
&lt;P&gt;Of course, there are some situations where that stops working. We'd still need this to fail, for instance: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;void M&amp;lt;T&amp;gt;(List&amp;lt;T&amp;gt; t1, List&amp;lt;T&amp;gt; t2){}&lt;BR&gt;...&lt;BR&gt;M(myListOfShorts, myListOfInts); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Generic types are neither covariant nor contravariant, so neither choice works in this case. However, it &lt;I&gt;does&lt;/I&gt; work in this case: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;void M&amp;lt;T&amp;gt;(Func&amp;lt;T&amp;gt; t1, Func&amp;lt;T&amp;gt; t2){}&lt;BR&gt;...&lt;BR&gt;M(()=&amp;gt;myInt, ()=&amp;gt;myShort); &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;because a lambda which returns a &lt;SPAN class=code&gt;short&lt;/SPAN&gt; &lt;EM&gt;is&lt;/EM&gt; convertible to a delegate which returns an &lt;SPAN class=code&gt;int&lt;/SPAN&gt;, so inference to &lt;SPAN class=code&gt;int&lt;/SPAN&gt; could succeed. &lt;/P&gt;
&lt;P&gt;The motivating example for all of this is the join scenario. For those of you who are not database wonks, joining is one of the fundamental operations on tabular data. You typically have two tables with some relationship between them. For instance, you might have a list of customers, where each customer has a customer id, and a list of orders where each order has an associated customer id. You "join" the tables by producing a new table of records associating each customer with their orders. Maybe the new table is the customer name and the amount of each of their orders.&lt;/P&gt;
&lt;P&gt;To represent a generic join operation as a method we need two tables of records, a key extractor for each table, and a projector from the joined records to the output records. The caller might look something like: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;var results = Join(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; myCustomers,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; myOrders,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; customer=&amp;gt;customer.Id,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; order=&amp;gt;order.CustomerId,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (customer, order)=&amp;gt;new {customer.Name, order.Price});&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;The fully generic method might look something like: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;IEnumerable&amp;lt;RES&amp;gt; Join&amp;lt;REC1, REC2, KEY, RES&amp;gt;(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;REC1&amp;gt; rec1s,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;REC2&amp;gt; rec2s,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;REC1, KEY&amp;gt; rec1KeyExtractor,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;REC2, KEY&amp;gt; rec2KeyExtractor,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Func&amp;lt;REC1, REC2, RES&amp;gt; projector) { ... }&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;So now perhaps you see the problem. What if the customer key type is &lt;SPAN class=code&gt;int &lt;/SPAN&gt;but the order table's customer key type is &lt;SPAN class=code&gt;Nullable&amp;lt;int&amp;gt; &lt;/SPAN&gt;? We would like to infer that &lt;SPAN class=code&gt;Nullable&amp;lt;int&amp;gt; &lt;/SPAN&gt;is the better choice for &lt;SPAN class=code&gt;KEY &lt;/SPAN&gt;but today the type inference algorithm insists on 100% consistency. &lt;/P&gt;
&lt;P&gt;As you can see, this is rapidly becoming complex. We would like to come up with an inference algorithm that solves this problem, but at the same time can be clearly described in the standard and understood by mortals. (Where by "understood by mortals" I mean "such that Eric has some chance of implementing the algorithm correctly"!) Any thoughts or comments you might have would be appreciated; the language design committee will be debating these issues this week and so this is the time to give feedback about these things. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=669993" 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></item><item><title>What Are The Semantics Of Multiple Implicitly Typed Declarations? Part Two</title><link>http://blogs.msdn.com/ericlippert/archive/2006/06/27/what-are-the-semantics-of-multiple-implicitly-typed-declarations-part-two.aspx</link><pubDate>Tue, 27 Jun 2006 20:08:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:648681</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>26</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/648681.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=648681</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Many thanks for all your input in my informal poll yesterday. The results were similar to other "straw polls" we've done over the last couple of months. In this particular poll the results were: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;var a=A, b=B;&lt;/SPAN&gt; where the expressions are of different types should: 
&lt;UL&gt;
&lt;LI&gt;have the same semantics as &lt;SPAN class=code&gt;var a=A; var b=B;&lt;/SPAN&gt;: 12&lt;/LI&gt;
&lt;LI&gt;replace the &lt;SPAN class=code&gt;var&lt;/SPAN&gt; with some type for both: 3&lt;/LI&gt;
&lt;LI&gt;give an error: 6&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;There were 18 comments; a few people voted twice, which is fine with me. &lt;/P&gt;
&lt;P&gt;The way the feature is specified is that the &lt;SPAN class=code&gt;var&lt;/SPAN&gt; is to be replaced with the best type compatible with all the expressions, to maintain the invariant that parallel declarations like this always give the same type to each variable. Many people that we've polled believe that this is the "intuitively obvious" choice, including much of the language design team. A larger group of language users believes that "infer each variable type&amp;nbsp;separately" is the "intuitively obvious" choice. &lt;/P&gt;
&lt;P&gt;So what to do?&amp;nbsp;We have a relatively unimportant edge-case feature where customers strongly disagree as to what the code "obviously" means, and the difference can lead to subtle bugs. That's clearly badness. Given this feedback, amply confirmed by you all, we are probably going to simply remove multiple implicitly typed declarations from the C# 3.0 language. &lt;/P&gt;
&lt;P&gt;Thanks for your feedback! &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=648681" 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></item><item><title>What Are The Semantics Of Multiple Implicitly Typed Declarations? Part One</title><link>http://blogs.msdn.com/ericlippert/archive/2006/06/26/what-are-the-semantics-of-multiple-implicitly-typed-declarations-part-one.aspx</link><pubDate>Mon, 26 Jun 2006 21:02:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:647606</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/647606.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=647606</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;In my earlier series on inferring a unique "best" type from a set of expressions I mentioned that one potential application of such an algorithm is in implicitly typed variables. This led to some good questions and concerns posted in the comments - questions and concerns which echo similar feedback we've been receiving from a variety of sources since we released the first technology preview of C# 3.0 last year. &lt;/P&gt;
&lt;P&gt;I'd like to run a quick unscientific poll to see what your intuitions and expectations about implicitly typed variables with multiple declarations are. Please leave a comment describing what you think should happen here, and why you think that. &lt;/P&gt;
&lt;P&gt;1: local variable declaration &lt;SPAN class=code&gt;var x = 1, y = 2.0;&lt;/SPAN&gt; has the same semantics as:&lt;BR&gt;(a) &lt;SPAN class=code&gt;double x = 1, y = 2.0; &lt;/SPAN&gt;&lt;BR&gt;(b) &lt;SPAN class=code&gt;int x = 1; double y = 2.0; &lt;/SPAN&gt;&lt;BR&gt;(c) &lt;SPAN class=code&gt;object x = 1, y = 2.0; &lt;/SPAN&gt;&lt;BR&gt;(d) this should be a compile-time error&lt;BR&gt;(e) something else, please specify&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;2: local variable declaration &lt;SPAN class=code&gt;var q = 0, r = (short)6;&lt;/SPAN&gt; has the same semantics as:&lt;BR&gt;(a) &lt;SPAN class=code&gt;int q = 0; short r = 6; &lt;/SPAN&gt;&lt;BR&gt;(b) &lt;SPAN class=code&gt;int q = 0, r = 6; &lt;/SPAN&gt;&lt;BR&gt;(c) &lt;SPAN class=code&gt;short q = 0, r = 6; &lt;/SPAN&gt;&lt;BR&gt;(d) &lt;SPAN class=code&gt;object q = 0, r = 6; &lt;/SPAN&gt;&lt;BR&gt;(e) this should be a compile-time error&lt;BR&gt;(f) something else, please specify&lt;BR&gt;&lt;/P&gt;
&lt;P&gt;Thanks! Next time I'll describe some of the pros and cons of each and what our current thinking is in this area. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=647606" 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></item><item><title>Type inference woes, part three</title><link>http://blogs.msdn.com/ericlippert/archive/2006/05/30/type-inference-woes-part-three.aspx</link><pubDate>Tue, 30 May 2006 16:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:610769</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/610769.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=610769</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;There were a lot of good comments and questions posted in the last two entries which deserve answers. However, I am once more off to the &lt;A href="http://blogs.msdn.com/ericlippert/archive/2004/07/12/181265.aspx"&gt;beaver-shark infested shores of the great Canadian inland sea&lt;/A&gt; for my annual summer vacation. I'll get to them when I'm back, in late June.&lt;/P&gt;
&lt;P&gt;Before I go I should mention what algorithms we're considering to solve the "infer the best type for this set of expressions" problem that is going to crop up all over the show in C# 3.0.&lt;/P&gt;
&lt;P&gt;We've got four candidates right now. Suppose you've got a set of expressions, E. The set of their types is T.&lt;/P&gt;
&lt;P&gt;Algorithm One: pick the unique type in T to which every type in T is implicitly convertible.&lt;/P&gt;
&lt;P&gt;This has the advantage of being simple and already in the specification. It has the disadvantages of being incompatible with existing behaviour and not handling typeless expressions well.&lt;/P&gt;
&lt;P&gt;Algorithm Two: pick the unique type in T to which every expression in E is implicitly convertible.&lt;/P&gt;
&lt;P&gt;This has the advantage of being what we actually implement. However it has the disadvantages of turning some corner cases that should work according to the spec (such as literal-zero-vs-short) into error cases.&lt;/P&gt;
&lt;P&gt;We could combine the two algorithms. Consider the subset of T consisting of all types in T to which every expression in E is implicitly convertible. Call this subset S. 
&lt;P&gt;
&lt;P&gt;Algorithm three: pick the unique type in S to which every type in S is implicitly convertible.&lt;/P&gt;
&lt;P&gt;This algorithm has considerable charm. As far as I've been able to determine, it is 100% backwards compatible with existing non-error behaviour, while at the same time turning those cases which ought to be successful according to Algorithm One back into success cases which agree with the spec. Literal-zero-vs-short would go to int. However, there is a down side, which is addressed by Algorithm Four.&lt;/P&gt;
&lt;P&gt;Algorithm Four: pick the unique type in S &lt;B&gt;from which&lt;/B&gt; every type in S is implicitly convertible. That is, pick the &lt;I&gt;smallest&lt;/I&gt; type in S, not the largest.&lt;/P&gt;
&lt;P&gt;This algorithm also maintains backwards compatibility but would make literal-zero-vs-short go to short. And isn't that better? If you have an implicitly typed array of ten thousand shorts, and you throw a single literal zero in there, you probably want it to stay as an array of shorts. Given the choice of several types to which every expression goes, surely picking the smallest is the best choice.&lt;/P&gt;
&lt;P&gt;Algorithm Four is currently the front-runner in our thinking but of course I am blogging about this in the first place because there is still time for feedback. Any thoughts on these choices, or ideas for better algorithms, would be appreciated.&lt;/P&gt;
&lt;P&gt;Many thanks to my colleauges &lt;A href="http://blogs.msdn.com/wesdyer/"&gt;Wes&lt;/A&gt; and &lt;A href="http://blogs.msdn.com/peterhal/"&gt;Peter&lt;/A&gt; for their analyses of these algorithms.&lt;/P&gt;
&lt;P&gt;See you when I'm back!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=610769" 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></item><item><title>Type inference woes, part two</title><link>http://blogs.msdn.com/ericlippert/archive/2006/05/26/type-inference-woes-part-two.aspx</link><pubDate>Fri, 26 May 2006 19:29:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:608176</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/608176.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=608176</wfw:commentRss><description>&lt;P class=mine&gt;So what's the big deal anyway? The difference between the spec and the implementation is subtle, only affects a few specific and rather unlikely scenarios, and can always be worked around by inserting casts if you need to. Fixing the implementation would be a breaking change, it seems like a small and simple change to the specification, so why don't we just update the specification the next time we get the chance and be done with it?&lt;/P&gt;
&lt;P class=mine&gt;The big deal is that this is a small, isolated, corner case problem for C# 2.0, but it becomes much more visible in C# 3.0. Essentially the question here is "given a set of expressions of various types, how do we infer a unique unified type?" In C# 2.0 this question comes up only in the context of the &lt;SPAN class=code&gt;?:&lt;/SPAN&gt; operator, and the set always has two elements. In C# 3.0, this question comes up all over the place and the sets can be arbitrarily large. For example:&lt;/P&gt;
&lt;DIV class=mine&gt;
&lt;UL&gt;
&lt;LI&gt;When an implicitly typed local variable declaration statement contains several declarations, does&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=code&gt;const short s = 123;&lt;BR&gt;var x = 0, y = s;&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;infer that &lt;SPAN class=code&gt;x&lt;/SPAN&gt; and &lt;SPAN class=code&gt;y&lt;/SPAN&gt; are &lt;SPAN class=code&gt;short&lt;/SPAN&gt;, or &lt;SPAN class=code&gt;int&lt;/SPAN&gt;, or is this an error? &lt;/LI&gt;
&lt;LI&gt;Does the implicitly typed array initializers&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=code&gt;const short s = 123;&lt;BR&gt;var x = new[] {0, s};&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;infer &lt;SPAN class=code&gt;x&lt;/SPAN&gt; to be &lt;SPAN class=code&gt;short[]&lt;/SPAN&gt;, &lt;SPAN class=code&gt;int[]&lt;/SPAN&gt;, or is this an error? 
&lt;LI&gt;When a lambda expression is passed to a generic method we must infer the return type of the lambda from the set of expressions returned from its body: &lt;BR&gt;&lt;BR&gt;&lt;SPAN class=code&gt;public static IEnumerable&amp;lt;T&amp;gt; Select&amp;lt;S, T&amp;gt;(IEnumerable&amp;lt;S&amp;gt; collection, Func&amp;lt;S, T&amp;gt; projection){//...&lt;BR&gt;...&lt;BR&gt;const short s = 123;&lt;BR&gt;var x = Select(blahCollection, c =&amp;gt; { if (c.Foo &amp;gt; c.Bar) return 0; else return s; }); &lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;If &lt;SPAN class=code&gt;S&lt;/SPAN&gt; is inferred to be &lt;SPAN class=code&gt;Blah&lt;/SPAN&gt;, is &lt;SPAN class=code&gt;x&lt;/SPAN&gt; inferred to be &lt;SPAN class=code&gt;IEnumerable&amp;lt;short&amp;gt;&lt;/SPAN&gt;, or &lt;SPAN class=code&gt;IEnumerable&amp;lt;int&amp;gt;&lt;/SPAN&gt;, or is this an error? &lt;/LI&gt;
&lt;LI&gt;When multiple lambda expressions are passed to a generic method, can we unify unequal inferred types?&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=code&gt;public static IEnumerable&amp;lt;T&amp;gt; Join&amp;lt;O, I, K, R&amp;gt;(&lt;BR&gt;IEnumerable&amp;lt;O&amp;gt; outer, &lt;BR&gt;IEnumerable&amp;lt;I&amp;gt; inner, &lt;BR&gt;Func&amp;lt;O, K&amp;gt; outerkey, &lt;BR&gt;Func&amp;lt;I, K&amp;gt; innerkey, &lt;BR&gt;Func&amp;lt;O, I, R&amp;gt; selector) { // ...&lt;BR&gt;&lt;BR&gt;var x = Join(customers, orders, c =&amp;gt; c.Id, o =&amp;gt; o.CustId, &lt;BR&gt;(c, o) =&amp;gt; new {c.Name, o.Amount});&lt;BR&gt;&lt;BR&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;&lt;/SPAN&gt;
&lt;DIV class=mine&gt;
&lt;P&gt;Suppose &lt;SPAN class=code&gt;Customer.Id&lt;/SPAN&gt; is &lt;SPAN class=code&gt;int&lt;/SPAN&gt; and &lt;SPAN class=code&gt;Order.CustId&lt;/SPAN&gt; is &lt;SPAN class=code&gt;Nullable&amp;lt;int&amp;gt;&lt;/SPAN&gt;. Do we infer that &lt;SPAN class=code&gt;K&lt;/SPAN&gt; is &lt;SPAN class=code&gt;Nullable&amp;lt;int&amp;gt;&lt;/SPAN&gt;, or produce an error? 
&lt;P&gt;Enquiring minds want to know the answers to these questions, and it seems sensible that we should come up with a single algorithm that answers all of them. And if we're going to do that, then it seems desirable that &lt;SPAN class=code&gt;?:&lt;/SPAN&gt; ought to use the same algorithm we come up with for all of the above.&lt;/P&gt;
&lt;P&gt;After the Memorial Day break I'll discuss some of the algorithms that we're considering, and what benefits and drawbacks they have. Have a good weekend!&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=608176" 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></item><item><title>Type inference woes, part one</title><link>http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woes-part-one.aspx</link><pubDate>Wed, 24 May 2006 22:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:606278</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/606278.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=606278</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;The C# compiler has a subtle violation of the specification which raises an interesting question for some of the new LINQ-related features. The specification for the &lt;SPAN class=code&gt;?:&lt;/SPAN&gt; operator states the following:&lt;/P&gt;
&lt;DIV class=spec&gt;
&lt;P&gt;The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If X and Y are the same type, then this is the type of the conditional expression. 
&lt;LI&gt;Otherwise, if an implicit conversion exists from X to Y, but not from Y to X, then Y is the type of the conditional expression. 
&lt;LI&gt;Otherwise, if an implicit conversion exists from Y to X, but not from X to Y, then X is the type of the conditional expression. 
&lt;LI&gt;Otherwise, no expression type can be determined, and a compile-time error occurs. &lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
&lt;P&gt;This makes a lot of sense. If you have&lt;/P&gt;
&lt;DIV class=code&gt;
&lt;P&gt;Giraffe g = (a &amp;gt; b) ? new Giraffe() : new Mammal();&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;then you ought to get a type error. The type of the ternary expression should be &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt;, not &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;, because &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt; goes to &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt; but &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt; does not go to &lt;SPAN class=code&gt;Giraffe&lt;/SPAN&gt;.&lt;/P&gt;
&lt;P&gt;If both types go to the other (which can happen if both types define an implicit conversion operator for the other) then we can't decide which one is better and give up.&lt;/P&gt;
&lt;P&gt;If neither type goes to the other, then notice that we do not attempt to find the "nearest encompassing type". For example, if we had&lt;/P&gt;
&lt;DIV class=code&gt;
&lt;P&gt;Mammal m = (a &amp;gt; b) ? new Dog() : new Cat();&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;then we would again get a type error. We want to be able to have a unique type as the type of the ternary expression. We do not want to get into the business of saying "well, &lt;SPAN class=code&gt;Dog&lt;/SPAN&gt; and &lt;SPAN class=code&gt;Cat&lt;/SPAN&gt; are both subclasses of &lt;SPAN class=code&gt;Mammal&lt;/SPAN&gt;, but they are also both implementors of &lt;SPAN class=code&gt;IHousepet&lt;/SPAN&gt;, so which one is the "real" nearest encompassing type?" It's just too big a can of worms. We like the principle that the type of the expression must be the type of something in the expression.&lt;/P&gt;
&lt;P&gt;So where's the spec violation? Well, according to the specification above, is this legal?&lt;/P&gt;
&lt;DIV class=code&gt;
&lt;P&gt;short s = 123;&lt;BR&gt;int i = (a &amp;gt; b) ? 0 : s;&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;X is &lt;SPAN class=code&gt;int&lt;/SPAN&gt;, Y is &lt;SPAN class=code&gt;short&lt;/SPAN&gt;. Y goes to X, X does not go to Y, therefore X is the type of the expression, so this should work. But in fact, C# reports this as an error, because the rule C# actually implements is:&lt;/P&gt;
&lt;DIV class=spec&gt;
&lt;P&gt;Let B and C be the second and third operands. Let X and Y be the types of the second and third operands. Then,&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If X and Y are the same type, then this is the type of the conditional expression. 
&lt;LI&gt;Otherwise, if an implicit conversion exists from B to Y, but not from C to X, then Y is the type of the conditional expression. 
&lt;LI&gt;Otherwise, if an implicit conversion exists from C to X, but not from B to Y, then X is the type of the conditional expression. 
&lt;LI&gt;Otherwise, no expression type can be determined, and a compile-time error occurs. &lt;/LI&gt;&lt;/UL&gt;&lt;/DIV&gt;
&lt;P&gt;Since the types are not the same, and literal zero goes to &lt;SPAN class=code&gt;short&lt;/SPAN&gt;, and &lt;SPAN class=code&gt;s&lt;/SPAN&gt; goes to &lt;SPAN class=code&gt;int&lt;/SPAN&gt;, no expression type can be determined and we report an error.&lt;/P&gt;
&lt;P&gt;One could make the argument that this is the better behaviour. It certainly does seem that in this case it's arguably ambiguous what the best type for the expression is since both halves can be converted to both &lt;SPAN class=code&gt;int&lt;/SPAN&gt; and &lt;SPAN class=code&gt;short&lt;/SPAN&gt;. &lt;/P&gt;
&lt;P&gt;Now, since this is an error case, surely we can simply fix the bug. We'd be turning a case which is presently an error into something which works. Turning broken code into working code is by definition not a breaking change -- a breaking change is turning working code into broken code, or working code with different semantics.&lt;/P&gt;
&lt;P&gt;Unfortunately, fixing this would be a breaking change:&lt;/P&gt;
&lt;DIV class=code&gt;
&lt;P&gt;public delegate int D();&lt;BR&gt;...&lt;BR&gt;D d = (a &amp;gt; b) ? (D)(delegate() { return 1; }) : delegate() { return 2; };&lt;/P&gt;&lt;/DIV&gt;
&lt;P&gt;Notice that the latter expression has no type at all. Yes, anonymous methods expressions are expressions without a type. If we used the "expression" version of the algorithm then the second expression is convertible to the type of the first, but the first is not convertible to the non-existant type of the second, so the type of the expression is the type of the first. If we used the spec-compliant "type" version then the second expression doesn't even have a type, so there's no type we can infer!&lt;/P&gt;
&lt;P&gt;Next time I'll talk about an algorithm that might save the day here, and also discuss how we'll need to generalize this to make some of the LINQ-related language features work.&lt;/P&gt;&lt;/DIV&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=606278" 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></item><item><title>Delegates, Lambdas, Type Inference and Long Playing Records</title><link>http://blogs.msdn.com/ericlippert/archive/2006/03/31/delegates-lambdas-type-inference-and-long-playing-records.aspx</link><pubDate>Fri, 31 Mar 2006 20:17:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:566058</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/566058.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=566058</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Today is my 33 1/3rd birthday! I'm one third of the way through my first century. I feel like I should go buy some LPs to celebrate, not that I have anything that will play them. &lt;/P&gt;
&lt;P&gt;In other news, someone sent me this code the other day. Suppose you've got a collection of mammals and you want to feed all the giraffes:&lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;delegate void Action&amp;lt;X&amp;gt;(X x);&lt;BR&gt;class MyCollection&amp;lt;T&amp;gt; : Collection&amp;lt;T&amp;gt; where T : class {&lt;BR&gt;&amp;nbsp; public void Apply&amp;lt;S&amp;gt;(Action&amp;lt;S&amp;gt; action) where S : class, T {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ( T t in this ) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; S&amp;nbsp;s =&amp;nbsp;t as S;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (s != null )&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; action(s);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;} &lt;BR&gt;//...&lt;BR&gt;&lt;BR&gt;MyCollection&amp;lt;Mammal&amp;gt; mammals = new MyCollection&amp;lt;Mammal&amp;gt;();&lt;BR&gt;//...&lt;BR&gt;mammals.Apply&amp;lt;Giraffe&amp;gt;(delegate(Giraffe g){Feed(g);});&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;This works just fine. The questioner was wondering why this didn't work: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;mammals.Apply(delegate(Giraffe g){Feed(g);});&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;That is, why do we need to specify the type parameter to the generic method? Shouldn't type inference take care of it? &lt;/P&gt;
&lt;P&gt;That would be nice, but unfortunately section 26.6.4 of the specification clearly states that nothing is inferred from any anonymous method, null, or method group argument. &lt;/P&gt;
&lt;P&gt;In the next version of C# we will have a new, more powerful, more flexible kind of anonymous method called a lambda expression. A lambda expression is like an anonymous method with additional type inferencing features and a more natural syntax than the clunky delegate syntax. &lt;/P&gt;
&lt;P&gt;Unfortunately for the questioner, the new lambda type inferencing rules actually will not help with this scenario. However, the new type inferencing rules will apply in any scenario where "classic" type inferencing can be used to determine the generic type of a lambda argument, and from that, determine the generic type of a lambda return, and from that, the generic return type of a delegate, and from that, a method type parameter.
&lt;/P&gt;
&lt;P&gt;That last sentence probably made no sense.  Let's look at an example where the new type inferencing rule would apply.&lt;/P&gt;
&lt;P&gt;Suppose you have a collection of Customers and you want to create a collection of their names: &lt;/P&gt;
&lt;P&gt;&lt;SPAN class=code&gt;delegate R Func&amp;lt;A, R&amp;gt; (A arg);&lt;BR&gt;IEnumerable&amp;lt;S&amp;gt; Select&amp;lt;T, S&amp;gt;(IEnumerable&amp;lt;T&amp;gt; source, Func&amp;lt;T, S&amp;gt; selector) {...}&lt;BR&gt;//... &lt;BR&gt;names = Select(customers, c =&amp;gt; c.Name);&lt;BR&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;With the old type inferencing rules we can infer that &lt;SPAN class=code&gt;T&lt;/SPAN&gt; is &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt;, and we would infer nothing from the lambda. However, in C# 3.0 we will enter a second round of type inferencing, where we'd note that we hadn't inferred anything from the lambda yet, and that it is being converted to a partially inferred delegate type &lt;SPAN class=code&gt;Func&amp;lt;Customer, R&amp;gt;&lt;/SPAN&gt; requiring type inference on the return type. &lt;/P&gt;
&lt;P&gt;We now can infer that the parameter to the lambda, &lt;SPAN class=code&gt;c&lt;/SPAN&gt; must be of type &lt;SPAN class=code&gt;Customer&lt;/SPAN&gt;, and therefore the return type of the lambda must be the type of &lt;SPAN class=code&gt;Customer.Name&lt;/SPAN&gt;, which is &lt;SPAN class=code&gt;string&lt;/SPAN&gt;. Therefore the delegate type is &lt;SPAN class=code&gt;Func&amp;lt;Customer, string&amp;gt;&lt;/SPAN&gt;, and hey,we've managed to infer the types of all the parameters to &lt;SPAN class=code&gt;Select&amp;lt;T, S&amp;gt;&lt;/SPAN&gt;, so we're done. &lt;/P&gt;
&lt;P&gt;Cool eh? Now all we've got to do is actually implement it... &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=566058" 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></item><item><title>C# 3.0 is still statically typed, honest!</title><link>http://blogs.msdn.com/ericlippert/archive/2005/09/27/c-3-0-is-still-statically-typed-honest.aspx</link><pubDate>Tue, 27 Sep 2005 20:03:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474462</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>23</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/474462.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=474462</wfw:commentRss><description>&lt;FONT face="lucida sans unicode"&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;Since LINQ was announced I've seen a lot of really positive feedback and a lot of questions and concerns. Keep 'em coming! We need this feedback so that we can both correct misconceptions early and get the design right now.&lt;/P&gt;
&lt;P&gt;One of the misconceptions that I've seen a lot over the last few days in forums, blog posts and private emails is a confusion about what the new "type inferencing" feature implies for the type safety of the language. Apparently we have not been sufficiently clear on this point: &lt;B&gt;C# 3.0 will be statically typed, just like&amp;nbsp;C# 1.0 and 2.0. The var declaration style does not introduce dynamic typing or duck typing to C#.&lt;/P&gt;&lt;/B&gt;
&lt;P&gt;I think the confusion may arise from familiarity with other languages such as JScript. In JScript this is perfectly legal:&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;var foo = new Blah();&lt;BR&gt;foo = 123;&lt;BR&gt;foo = "hello";&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;JScript is a dynamically typed language. You can assign any value of any type to a var.&lt;/P&gt;
&lt;P&gt;In C# 3.0, the var statement&amp;nbsp;means&amp;nbsp;"look at the type of the thing assigned to the variable, and act as though the variable was declared with that type." In other words, in C# the code above is just a syntactic sugar for&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;&lt;STRONG&gt;Blah&lt;/STRONG&gt; foo = new Blah();&lt;BR&gt;foo = 123;&lt;BR&gt;foo = "hello";&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;which of course would produce a type error on the second and third lines.&lt;/P&gt;
&lt;P&gt;If you take a look at section 26.1 of the C# 3.0 specification you'll see that the var statement has a lot of restrictions on it to ensure that the compiler always has enough information to make the correct type inference. Namely:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;the declarator must include an initializer, so that we can infer the type of the variable from the type of the initializer&lt;/LI&gt;
&lt;LI&gt;the initializer has to be something that we can figure out the type of – not null or a collection initializer&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Compare this to JScript .NET, which has a much stronger type inference mechanism. JScript .NET does not require initializers in var statements; the compiler tracks all assignments to the variable and infers the best type. If, say, only strings are assigned to a variable then it will infer the string type. JScript .NET also infers return types of functions by a similar mechanism. But the goal of the JScript .NET type inference mechanism was to &lt;STRONG&gt;increase the performance of legacy dynamically typed code&lt;/STRONG&gt;. If we can infer a type and thereby generate faster, smaller code, we do so.&amp;nbsp; If not, we don't.&lt;/P&gt;
&lt;P&gt;Then why introduce this syntactic sugar in C# 3.0? C# doesn't have a body of legacy dynamic code like JScript and already generates efficient code.&lt;/P&gt;
&lt;P&gt;There are two reasons, one which exists today, one which will crop up in 3.0. &lt;/P&gt;
&lt;P&gt;The first reason is that this code is incredibly ugly because of all the redundancy:&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt; mylists = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;And that's a simple example – I've written worse. Any time you're forced to type exactly the same thing twice, that's a redundancy that we can remove. Much nicer to write&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face="Lucida Console" color=#333399 size=2&gt;
&lt;P&gt;var mylists = new Dictionary&amp;lt;string, List&amp;lt;int&amp;gt;&amp;gt;();&lt;/P&gt;&lt;/FONT&gt;&lt;FONT color=#800080 size=2&gt;
&lt;P&gt;and let the compiler figure out what the type is based on the assignment.&lt;/P&gt;
&lt;P&gt;Second, C# 3.0 introduces anonymous types. Since anonymous types by definition have no names, you need to be able to infer the type of the variable from the initializing expression if its type is anonymous.&lt;/P&gt;
&lt;P&gt;We'll discuss the reasoning behind anonymous types in another post.&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=474462" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript+.NET/default.aspx">JScript .NET</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</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/Type+Inference/default.aspx">Type Inference</category></item></channel></rss>