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

// declaration
void Method<T>(T obj, Func<string, T> func);

// call
Method("obj", s => (object) s);

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

第一阶段

  • 如果EI是匿名函数,则 显式参数类型推断 (§7.5.2.7)是从EI到TI制造的

    ⇒没有效果,因为Lambda表达式没有明确的参数类型。对?

  • 否则,如果EI具有U型U,而Xi是值参数,则 较低的推理 是从u到ti制成的。

    ⇒第一个参数是静态类型的 string, ,所以这添加了 string 到下限 T, , 对?

第二阶段

  • 全部 没有固定 类型变量XI不 取决于 (§7.5.2.5)任何XJ都是固定的(§7.5.2.10)。

    T 没有固定; T 不依赖任何东西...所以 T 应该修复,对吗?

§7.5.2.11修复

  • 候选人类型UJ的集合开始为XI范围集中的所有类型集。

    ⇒ { string (下限)}

  • 然后,我们依次检查XI的每个界限:[...]对于XI的每个下限U,从候选集合中删除U的所有类型UJ的UJ。 [...

    ⇒没有从候选人组中删除任何内容,对吗?

  • 如果在其余的候选类型UJ中,有一个唯一的类型V,从中有隐含的转换到所有其他候选类型,则XI已固定为V。

    ⇒由于只有一种候选人类型,这是真实的,因此XI固定为 string. 。对?


那我要去哪里?

有帮助吗?

解决方案

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

规格是错误的,因为它在第二阶段中犯了事件的顺序。我们应该指定我们进行输出类型推断 我们修复了非依赖性参数。

伙计,这东西很复杂。我对规格的这一部分重写的次数超出了我的记忆。

我以前曾经看过这个问题,我清楚地回想起进行修订,以使不正确的术语“类型变量”被“类型参数”替换为“类型变量”。 (类型参数不是存储位置,其内容可能会有所不同,因此将其称为变量是没有意义的。)我认为同时我指出订购是错误的。可能发生的可能是我们不小心在网络上运送了旧版本的规格。许多道歉。

我将与MADS合作以更新规格以匹配实现。我认为第二阶段的正确措辞应该这样做:

  • 如果不存在未连接的类型参数,则类型推断成功。
  • 否则,如果存在一个或多个参数EI具有相应的参数类型Ti,则具有TI类型的EI的输出类型至少包含一个未固定的类型参数XJ,而Ti类型的EI的输入类型都不包含任何未固定的类型参数XJ,然后从所有此类EI到Ti进行输出类型推断。

无论上一步是否实际上做出了推断,我们现在必须至少修复一个类型的参数,如下:

  • 如果存在一个或多个类型的参数XI,以使XI未固定,并且XI具有一组非空的边界,并且XI不依赖于任何XJ,则每个此类XI均已固定。如果任何固定操作失败,则输入推理失败。
  • 否则,如果存在一个或多个类型的参数XI,以使XI取消使用,并且XI具有一组非空的界限,并且至少有一个类型的参数XJ取决于XI,则每个此类XI均已固定。如果任何固定操作失败,则输入推理失败。
  • 否则,我们将无法取得进步,并且存在未连接的参数。类型推理失败。

如果类型推断既不会失败也没有成功,则重复第二阶段。

这里的想法是,我们要确保该算法永远不会进入无限循环。在第二阶段的每一次重复中,它要么成功,失败或取得进步。它不可能比有类型参数要修复到类型的循环次数更多。

感谢您引起我的注意。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top