Why can't I use a lambda expression inside Tuple.Create?

I know that the compiler can drop from lambda expressions in Predicate.

For example:

Predicate<int> p = x => true; 

is good.

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

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

and I got a compilation error:

Type arguments for the 'System.Tuple.Create (T1)' method cannot be taken out of use. Try explicitly specifying type arguments.

My question is this is a mistake, where is the ambiguity here?

(I know that I can fix this by casting: t = Tuple.Create((Predicate<int>)(x => true)); but I want to understand why the first method does not work, and I also do not want to do the casting, to save input :)

+7
c # lambda tuples delegates predicate
source share
3 answers

where is the ambiguity here?

The ambiguity here is that the compiler is not trying to output the lambda expression passed to Tuple.Create based on the left side, which already declares the desired type. What happens is a type input algorithm that gets called (no matter how you declare the type of the variable), and you cannot find a suitable match for your lambda expression because it does not have enough information.

This can be easily fixed with a tuple type declaration and an explicit message to the compiler how to output the lambda expression:

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

If you want to get into the type inference algorithm and see why it does not work:

Given:

 Tr M<X1โ€ฆXn>(T1 x1 โ€ฆ Tm xm) 

When a method of the form M (E1 ... Em) is called, the type inference task is to search for unique arguments of type S1 ... Sn for each of the parameters of type X1 ... Xn so that M (E1 ... Em) is called.

Now we start:

7.5.2.1 First phase:

For each of the arguments to the Ei method:

If Ei is an anonymous function, the explicit parameter type (ยง7.5.2.7) is inferred from Ei to Ti

So, we will see what makes the explicit type inference:

7.5.2.7 Explicit parameter type expressions

The explicit type of the parameter is derived from the expression E to type T in the following way:

. If E is a clearly expressed anonymous function with parameter types U1 ... Uk and T is a delegate type or an expression tree type with parameter types V1 ... Vk, then for each Ui the exact output (ยง7.5.2.8) is made from Ui to the corresponding Vi.

Your anonymous function is not explicitly typed, so the compiler is not able to draw accurate conclusions from the type of the Ui..Uk parameter to properly overload Tuple.Create .

+7
source share

The Tuple.Create method accepts general type parameters. The compiler can usually guess what types these are when you name it. However, with the help of a predicate, he cannot understand in any way. Some solutions:

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

Or I suggest you just specify a parameter of the type:

 var t = Tuple.Create<Predicate<int>>(x => true); 
+3
source share

To give a slightly different perspective than the existing answers:

C # language is designed so that in

 t = Tuple.Create(x => true); 

type Tuple.Create(x => true) is independent of t . This simplifies C # analysis in order to simplify the discussion of C # code in order to simplify the implementation of decent error messages for invalid C # code.

Now, given this, how should the compiler determine that Tuple.Create(x => true) should treat x => true as a Predicate<int> , rather than, say, a Func<int, bool> ? There is not enough information to determine this, except where the design compiler does not check.

+1
source share

All Articles