为什么我不能在Tuple.Create中使用lambda表达式?

Ere*_*rez 7 c# lambda delegates tuples predicate

我知道编译器可以从lambda表达式转换为Predicate.

例如:

Predicate<int> p = x => true;
Run Code Online (Sandbox Code Playgroud)

很好.

但是当我想创建一个包含谓词的元组时.我试着这样做(简化版):

Tuple<Predicate<int>> t;
t = Tuple.Create(x => true);
Run Code Online (Sandbox Code Playgroud)

我收到了编译错误:

无法从用法推断出方法'System.Tuple.Create(T1)'的类型参数.尝试显式指定类型参数.

我的问题是这是一个错误,这里的歧义在哪里?

(我知道我可以通过强制转换修复它:t = Tuple.Create((Predicate<int>)(x => true)); 但是我想理解为什么第一种方式不好,而且我也不想进行转换以节省输入:)

Yuv*_*kov 7

这里含糊不清哪里?

这里的歧义是编译器不会尝试推断传递给Tuple.Create基于已经声明所需类型的左侧的lambda表达式.会发生什么样的类型推断算法(无论你声明变量的类型),并且找不到与lambda表达式匹配的合适匹配,因为它没有足够的信息.

通过声明元组的类型并明确告诉编译器如何推断lambda表达式,可以很容易地解决这个问题:

t = Tuple.Create<Predicate<int>>(x => true);
Run Code Online (Sandbox Code Playgroud)

如果您想进入类型推断算法并查看它失败的原因:

鉴于:

Tr M<X1…Xn>(T1 x1 … Tm xm)
Run Code Online (Sandbox Code Playgroud)

通过形式M(E1 ... Em)的方法调用,类型推断的任务是为每个类型参数X1 ... Xn找到唯一类型参数S1 ... Sn,使得调用M(E1 ... Em)变为有效.

现在我们开始:

7.5.2.1第一阶段:

对于每个方法参数Ei:

如果Ei是匿名函数,则从Ei到Ti进行显式参数类型推断(第7.5.2.7节)

所以我们看一下显式参数类型推断的作用:

7.5.2.7显式参数类型推断

通过以下方式从表达式E到类型T进行显式参数类型推断:

·如果E是具有参数类型U1 的显式类型匿名函数 ... Uk和T是具有参数类型V1 ... Vk的委托类型或表达式树类型,则对于每个Ui,从Ui到ui进行精确推断(第7.5.2.8节)相应的Vi.

您的匿名函数不是显式类型,因此编译器无法从参数类型Ui..Uk进行精确推断到正确的重载Tuple.Create.