Martijn
Martijn

Reputation: 12102

When can C# infer the type of a parameter?

Why does the following correctly infer the type of T:

void foo<T>(IEnumerable<T> src){
  src.Select(id => id);
}

But this doesn't:

Func<T, T> Id<T>() {
  return (T t) => t;
}

void foo() {
  new List<int>().Select(Id());
}

Upvotes: 2

Views: 574

Answers (2)

isxaker
isxaker

Reputation: 9496

Section 7.4.2 Type Inference

If the supplied number of arguments is different than the number of parameters in the method, then inference immediately fails. Otherwise, assume that the generic method has the following signature:

Tr M(T1 x1 … Tm xm)

With a method call of the form M(E1 …Em) the task of type inference is to find unique type arguments S1…Sn for each of the type parameters X1…Xn so that the call M(E1…Em)becomes valid.

This code should work fine:

Func<T, T> Id<T>()
{
       return (T t) => t;
}

void foo()
{
      new List<int>().Select(Id<int>());
}

Upvotes: 1

Jon Skeet
Jon Skeet

Reputation: 1502985

Type argument inference always works on method arguments - including the first argument to an extension method like Select.

So your second call is effectively:

Enumerable.Select(new List<int>(), Id())

Select will be able to use those arguments to infer the type argument there, but the Id() call doesn't have any arguments, and type inference doesn't try to work out what the type argument should be based on how the method is used.

In other words, it's not Select that's the problem here - it's Id(). So this would work:

// No type inference available
var idFunc = Id<int>();
// Type argument to Select is inferred
var selection = new List<int>.Select(idFunc);

Upvotes: 8

Related Questions