理解语言规范中描述的C#types推断的问题

C#语言规范描述了第7.5.2节中的types推断。 有一个细节,我不明白。 考虑以下情况:

// declaration void Method<T>(T obj, Func<string, T> func); // call Method("obj", s => (object) s); 

Microsoft和Mono C#编译器都正确地推断T = object ,但是我对规范中的algorithm的理解会产生T = string ,然后失败。 这是我的理解:

第一阶段

  • 如果Ei是一个匿名函数,则从Ei到Ti创build一个明确的参数types推断 (第7.5.2.7节)

    ⇒没有效果,因为lambdaexpression式没有明确的参数types。 对?

  • 否则,如果Ei具有typesU并且xi是值参数,则从U到Ti进行下限推断

    ⇒第一个参数是静态types的string ,所以这将string添加到T的下限,对不对?

第二阶段

  • 所有不依赖于 (§7.5.2.5)任何Xj的非固定typesvariablesXi是固定的(§7.5.2.10)。

    ⇒T是不固定的; T不依赖于任何东西…所以T应该是固定的,对吧?

§7.5.2.11修复

  • 候选typesUj的集合始于Xi的边界集合中的所有types的集合。

    ⇒{ string (下界)}

  • 然后,我们依次检查Xi的每个边界:对于Xi的每个下界U,从候选集合中删除所有typesUj,其中不存在从U的隐式转换。 […]

    ⇒不会从候选集中删除任何东西,对吗?

  • 如果在剩余的候选typesUj中存在唯一的typesV,从其中隐含地转换到所有其他候选types,则将Xi固定为V.

    ⇒由于只有一个候选types,所以这是真实的,所以Xi被固定为string 。 对?


那么我哪里错了?

更新:我今天早上在公共汽车上的初步调查是不完整的和错误的。 第一阶段规范的文本是正确的。 执行是正确的。

规范是错误的,因为它在第二阶段得到错误的顺序。 修复非依赖参数之前 ,应该指定我们进行输出types推理。

男人,这东西很复杂。 我已经重写了规范的这一部分,比我记得更多的时间。

之前我看到过这个问题,而且我清楚地记得做了一些修改,使得不正确的术语“typesvariables”被“types参数”所替代。 (types参数不是内容可以变化的存储位置,所以把它们称为variables是没有意义的。)我认为同时我注意到sorting是错误的。 可能发生了什么,我们意外地在网上发布了旧版本的规格。 很多道歉。

我将与Mads合作,使规范更新以匹配实现。 我认为第二阶段正确的措辞应该是这样的:

  • 如果不存在不固定的types参数,则types推断成功。
  • 否则,如果存在具有相应参数typesTi的一个或多个参数Ei,使得具有typesTi的Ei的输出types包含至less一个未定型types参数Xj,并且具有typesTi的Ei的inputtypes都不包含任何未定型types参数Xj,则从所有这样的Ei到Ti进行输出types推断。

无论前面的步骤是否实际推理,我们现在必须至less修复一个types参数,如下所示:

  • 如果存在一个或多个types参数Xi,使得Xi不是固定的,并且Xi具有非空的边界集合,并且Xi不依赖于任何Xj,那么每个这样的Xi是固定的。 如果任何修复操作失败,则input推理失败。
  • 否则,如果存在一个或多个types参数Xi,使得Xi不是固定的,并且Xi具有非空的边界集合,并且存在至less一个依赖于Xi的types参数Xj,那么每个这样的Xi是固定的。 如果任何修复操作失败,则input推理失败。
  • 否则,我们无法取得进展,并有不确定的参数。 types推断失败。

如果types推理既不失败也不成功,那么重复第二阶段。

这里的想法是我们要确保algorithm永远不会陷入无限循环。 在第二阶段的每一次重复中,要么成功,失败,要么取得进展。 它不可能循环更多的时间比有types参数来修复types。

感谢您将此引起我的注意。