Lambdas and output type

I am having trouble understanding the reason why the following code gives me an error:

var funs = Enumerable.Range(0, 10).Select(x => (int y) => x + y); foreach (var fun in funs) Console.WriteLine("{0}", fun(10)); 

Error: β€œAn implicitly typed declaration of a local variable cannot be initialized usingβ€œ System.Collections.Generic.IEnumerator.Current. ”I know how to fix this (either by selecting the type to select, for example, Select<int, Func<int, int>> , or using a helper method such as private static Func<T1, TR> MakeFunc<T1, TR>(Func<T1, TR> f) { return f; } and using Select(x => MakeFunc(y => x + y)) .

However, I would like to understand the reason why the compiler cannot deduce types. So far, I guess, according to 7.15.6, he cannot figure out if he should translate the inner lambda to Func or Expr. Is it right or is there something else?

For reference, here is what 7.15.6 says:

β€œAn anonymous function F must always be converted to a delegate type D or an expression tree of type E either directly or through the execution of the delegate creation expression new D (F). This conversion determines the result of the anonymous function.”

+4
source share
1 answer

The reason is simple:

HOW can compilation conclude that it should be Func<int, int> ? He just can't!

Suppose you have your own delegate:

  public delegate int F(int i); 

How could the compiler choose between Func<int, int> and F ? These are completely different types that have two common features: there are both delegates and have the same signature (one parameter and return type, both int types).

Therefore, the compiler cannot select; you will have to do this:

 var funs = Enumerable.Range(0, 10).Select<int, Func<int,int>>(x => y => x + y); 

or

 var funs = Enumerable.Range(0, 10).Select<int, F>(x => y => x + y); 

One small advantage: you can drop int to y .

+1
source

Source: https://habr.com/ru/post/1481641/


All Articles