Why can not I use the lambda expression in Tuple.Create?

advertisements

I know that the compiler can cast from lambda expression to Predicate.

For example:

Predicate<int> p = x => true;

is good.

But when I want to create a tuple that holds a Predicate. I tried to do this (simplified version):

Tuple<Predicate<int>> t;
t = Tuple.Create(x => true);

and I got the compilation error:

The type arguments for method 'System.Tuple.Create(T1)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

My question is what this is an error, where is the ambiguity here?

(I know I can fix it by casting:t = Tuple.Create((Predicate<int>)(x => true)); but I want to understand why the first way is not good, and also I want not to do the casting to save typing :)


where is the ambiguity here?

The ambiguity here is that the compiler doesn't attempt to infer the lambda expression passed to Tuple.Create based on the left hand side which already declares the desired type. What happens is type inference algorithm kicks in (regardless of you declaring the type of the variable), and fails to find a suitable match to your lambda expression as it doesn't have enough information.

This can be easily fixed with declaring the type of the tuple and explicitly telling the compiler how to infer the lambda expression:

t = Tuple.Create<Predicate<int>>(x => true);

If you want to get into the type inference algorithm and see why it fails:

Given:

Tr M<X1…Xn>(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.

Now we start:

7.5.2.1 The first phase:

For each of the method arguments Ei:

If Ei is an anonymous function, an explicit parameter type inference (§7.5.2.7) is made from Ei to Ti

So we look what explicit parameter type inference does:

7.5.2.7 Explicit parameter type inferences

An explicit parameter type inference is made from an expression E to a type T in the following way:

· If E is an explicitly typed anonymous function with parameter types U1…Uk and T is a delegate type or expression tree type with parameter types V1…Vk then for each Ui an exact inference (§7.5.2.8) is made from Ui to the corresponding Vi.

Your anonymous function isn't explicitly type, so the compiler has no way of doing an exact inference from the parameter type Ui..Uk to proper overload of Tuple.Create.