28

Possible Duplicate:
C# Why can't an anonymous method be assigned to var?

I have following statement in c#

Func <int, int, int> add = (x, y) => x + y;

But when I am replacing left hand side statement with following

var add = (x, y) => x + y;

I am getting compiler error(Cannot assign lambda expression to an implicitly-typed local variable).Why?

Community
  • 1
  • 1
santosh singh
  • 27,666
  • 26
  • 83
  • 129
  • Probably because it can't work out that x and y are `int`s. It's always useful to include the full error message in a question about it. – George Duckett Aug 01 '11 at 11:18
  • Because you need to specify the types of the arguments, as well as the return type – Rob Aug 01 '11 at 11:19
  • Cool, it seams to be a problem when you try to store an expression tree within an variable of the type var. Makes sense because the expression tree is evaluated at execution time... But really cool. ;) – Thorsten Hans Aug 01 '11 at 11:23
  • 2
    @Rob even if you specify the types of x and y (the return type is given by the expression implicitly) you'd still get "Cannot assign lambda expression to an implicitly typed variable" – Rune FS Aug 01 '11 at 11:27

3 Answers3

18

Because the compiler can't figure out what type the RHS has from

var add = (x, y) => x + y;

Any type that supports the + operator is a candidate and since the type of x and y is not constraint to be of the same type. There's quit a lot of possible + operators that could be used and therefore the set of possible types for x and y is rather large but to be able to determine the type of add, the compiler need to be able to reduce the set to just one type for x and one for y (not exactly true, it might be that both a base class and a derived class would fit) and still even if the compiler could figure out the type for x and y or that you specified the types to let's say int you'd still be left with the fact that both Expression<Func<int,int,int>> and Func<int,int,int> are possible types for add

There are multiple options for how to reduce the set of possible types. The compiler could try to look at how add is used later but doesn't (and potentially couldn't figure the types out even if it did)

Rune FS
  • 21,497
  • 7
  • 62
  • 96
  • 4
    As an addendum you can tell the compiler what is going on `var add = (Func)((x,y) => x + y);` but that doesn't really gain you anything as you may as well put the func on the LHS! – Bob Vale Jun 11 '13 at 08:39
  • But aren't it would be right for the compiler to make such a lambda polymorphic? – Hi-Angel Apr 07 '15 at 07:07
  • @Hi-Angel we are talking about knowing a concrete type of an object at compile time not about runtime resolution – Rune FS Apr 07 '15 at 15:14
  • @RuneFS of course. Is there a case when compiler couldn't infer a type at compile time? Given arguments *x* and *y* in a single expression has specific type, and also the specific type can be seen at return. – Hi-Angel Apr 07 '15 at 17:18
  • 1
    By the way, if it worked, it would be great addition to generics which for unknown reasons made limited. – Hi-Angel Apr 07 '15 at 17:39
  • Yes the example in the question (or any other lambda expression with at least one variable) is an example where the compile what be able to definately determine the type of the variable nor the return value. This is true for C#. Other languages like F# would actually be able to do this but that's due to the type system of F# which is more abstract/generic than that of C# – Rune FS Apr 07 '15 at 18:15
  • Not sure if your answer is really correct. For example you can't type `var someFunc = (int x, int y) => x + y;` even though that is not ambiguous. – Dave Cousineau Dec 02 '16 at 18:16
  • @Sahuagin that is still ambigious, because, as I note in my answer, it can both be a `Func` or an `Expression>` – Rune FS Dec 04 '16 at 20:02
  • More than half your answer says that it's because the parameters are ambiguous, which is not true. I don't think it's even really strictly because it's ambiguous between `Func` and `Expression`. The answers here make it sound like "it's ambiguous, therefore it doesn't compile", when it's really more like "it's ambiguous, therefore the language just blanketly does not allow it, therefore it does not compile" – Dave Cousineau Dec 04 '16 at 20:21
  • @Sahuagin the question is for a specific line of code. That specific line of code has no type declaration for the arguments, which makes it ambiguous as I describe in my answer. As I also describe adding them doesn't remove the ambiguity and since the specifications of type inference won't allow multiple possible types for the RHS it doesn't compile. Which is pretty much what I wrote in the first place. – Rune FS Dec 05 '16 at 21:11
  • 1
    Eh... but the ambiguity is irrelevant. The specific error is `An implicitly typed local variable declaration cannot be initialized with 'anonymous method'`. It does not give an error because it's ambiguous, it gives an error because the language does not allow it. Saying it's because it's ambiguous implies that if you could write it unambiguously it would all of a sudden be ok. The ambiguity has nothing to do with it, except as the reason why the designers of the language made it illegal. But as for why it's an error, it's because the language does not allow it. – Dave Cousineau Dec 07 '16 at 23:02
  • (...except as *one of* the reasons why the designers made it illegal.) – Dave Cousineau Dec 08 '16 at 00:03
  • @Sahuagin the error in question is `Cannot assign lambda expression to an implicitly-typed local variable` and the reason you can't is that there's no way to know the type of a lambda expression. Since it can be two different types. When a lambda expression is assigned, the compiler uses the type of the assigned variable/parameter to determine whether the lambda expression is a Fun or an ExpressionTree. And yes the design team chose that the lambda could have two types and that decision creates this scenario – Rune FS Dec 08 '16 at 22:16
  • 1
    `var formatDate = (DateTime dt) => dt.ToString("yyyy/MM/dd");`. It's perfectly clear that the input type is `DateTime` and the return type is `string`. No reason why that shouldn't be compilable as `Func`, except that the language can also compile the lambda as Expression>, so there is always that ambiguity. – Triynko Dec 15 '16 at 16:20
13

The var keyword will not work, because lambda expressions are used for both delegates as expression trees and the compiler does not know to which it should convert the lambda. In other words, the following types are valid for your (x, y) => x + y lambda: Func<int, int, int> and Expression<Func<int, int, int>>.

Steven
  • 166,672
  • 24
  • 332
  • 435
1

The error you are getting is because the compiler does not know what type x and y are.

Emond
  • 50,210
  • 11
  • 84
  • 115
  • @Emo:You are right.but we know that var keyword infer type from right hand side statement. – santosh singh Aug 01 '11 at 11:24
  • 2
    even if you specify the types of x and y you still get an error: "Cannot assign lambda expression to an implicitly typed variable" – Rune FS Aug 01 '11 at 11:25
  • @geek `var` will infer the type, but the right-hand side tells the compiler nothing specific about `x` and `y` (only that they have an operator `+` defined). – George Duckett Aug 01 '11 at 11:26
  • 2
    This is just false. Even if you type `var someFunc = (int x, int y) => x + y;` it does not work. – Dave Cousineau Dec 02 '16 at 18:16