Type inference for nested common functions

I was looking a bit for type inference, but I can't apply any solutions to my specific problem.

I am working on creating and passing functions. It seems to me that it should be able to deduce the int type. The only thing I can think of is that the return type of the lambda is not checked by the type inference algorithm. I shared unnecessary logic to show the problem more clearly.

Func<T> Test<T>(Func<Func<T>> func) { return func(); } 

this compiles:

 Func<int> x = Test<int>(() => { int i = 0; return () => i; }); 

but this gives the error "Type arguments for the method cannot be taken out of use. Try to explicitly specify type arguments":

 Func<int> x = Test(() => { int i = 0; return () => i; }); 

I think I just wanted to know why it works this way and some workarounds.

+6
source share
1 answer

I would say that the correct answer to the question is asked by E.Lippert in SO Why can't anonymous method be assigned to var?

But let's play a little with your example:

 Func<Func<int>> f = () => { int i = 0; return () => i; }; Func<int> x = Test(f); //it compiles OK 

No problem with the output type with your Func<T> Test<T>(Func<Func<T>> func) here. The problem is hidden in that you are using an anonymous lambda expression whose type cannot be inferred. Try the following:

 var f = () => { int i = 0; return () => i; }; 

It gives compiler error CS0815 , saying

Cannot assign lambda expression to implicitly typed local variable

and explanation:

An expression that is used as an initializer for an implicitly typed variable must be of type. Because anonymous function expressions, method group expressions, and a null literal expression are not type, they are not suitable initializers. An implicitly entered variable cannot be initialized to a null value in its declaration, although it can subsequently be set to null.

Now try another:

 var x = Test(() => { Func<int> f = () => 0; return f; }); 

It also compiles. So the problem with your original example was actually with this line:

 return () => i; 

We can go further and in accordance with what Eric Lippert says in his answer, provide another function to wrap this:

 static Func<T> GetFunc<T>(Func<T> f) { return f; } 

Now we can rewrite your code as follows:

 var x = Test(() => { int i = 0; return GetFunc(() => i); }); 

And it also works.

However, as I understand it, all this is overhead, and you should just provide an explicit type. Although these workarounds are suitable when you need to have a lambda, returning an anonymous type object.

+7
source

All Articles