【问题标题】:Fully qualified name, unqualified name with import declaration resolve differently完全限定名称,带有导入声明的非限定名称解析不同
【发布时间】:2023-03-24 03:19:01
【问题描述】:

这行得通

open System
let f = Action(fun () -> Unchecked.defaultof<_>)

但是这个

let f = System.Action(fun () -> Unchecked.defaultof<_>)

产生编译错误

存在多种类型,称为“Action”,采用不同数量的泛型参数。提供类型实例化以消除类型解析的歧义,例如'动作,,_,,,_,,,_>'.

我知道我可以通过添加类型参数占位符 (System.Action&lt;_&gt;(...)) 来修复它,但知道为什么它们的行为不同吗?

编辑

在规范中找到这个,第 14.1.9 节:

当打开模块或命名空间声明组F 时,将项目添加到名称环境中,如下所示:

  • 将类型添加到 TypeNames 表中。如果该类型具有 CLI 损坏的通用名称,例如 List'1,则在 ListList'1 下添加一个条目。

这种行为是否适用于完全限定类型(省略类型参数)?好像不是这样的。

【问题讨论】:

  • 关于new,请注意,当您使用new 调用构造函数时,您始终必须提供正确数量的泛型参数(例如,查看使用open System.Collections.Generics; new Dictionary() 时会发生什么,而不是只是Dictionary()。这意味着在您的第二次编辑中,您肯定会调用非泛型System.Action 构造函数而不是System.Action&lt;unit&gt; 构造函数。
  • @kvb:啊,是的——忘记了。我会从问题中删除它,因为它无关紧要。
  • @Daniel 您使用的是 .NET 3.5 还是 .NET 4.0?如果您不使用 4.0,我认为这个 Connect Bug connect.microsoft.com/VisualStudio/feedback/details/482934/… 可能与您的问题有关。
  • @James:这是 .NET 4.0,但问题看起来很相似。

标签: f#


【解决方案1】:

我同意@James 的观点,这与在 Connect 上提交的错误有关,但我认为情况略有不同。无论如何,我认为这不是预期的行为。您能否通过 microsoft dot comfsbugs 报告?

无论如何 - 我做了一些调试,这是我目前发现的:

似乎编译器使用不同的代码路径来解析名称Action和名称System.Action。在解析另一个时,它会在所有加载的模块(即程序集)中搜索名为 System.Action 的类型(请参阅开源版本的 nameres.fs file 中的 ResolveLongIndentAsModuleOrNamespaceThen 函数)。

这会找到Action 的两个定义(一个在mscorlib 中,另一个在System.Core 中)。我认为问题来自这样一个事实,即名称解析只是迭代结果 - 它找到第一个(来自System.Core),它没有可用的重载(因为它的范围从Action&lt;_,_,_,_,_&gt;到一个版本大约 15 个类型参数)。找到这种类型后,它甚至不查看是否有其他类型(在另一个程序集中)可以使用就报告错误。

如果您不引用系统程序集,则 F# 编译器可以很好地解决重载问题。运行不带参数的编译器会引用默认的程序集集,所以这不起作用:

fsc test.fs 

但是如果我添加 --noframework 标志,那么它编译没有问题:

fsc --noframework test.fs

【讨论】:

  • 感谢您为解释这一点所做的工作。我已经提交了错误报告。
  • @Daniel 和 Tomas:对此有后续跟进吗?从 F# 3.1.2 开始,它是 continues to cause confusion,我在 Codeplex 问题跟踪器上的限定名称上看不到任何内容。似乎错误报告没有得到解决。 这有点令人难过,因为这个问题很快就会出现三年。
猜你喜欢
  • 2015-02-23
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 2022-06-15
  • 2016-06-30
相关资源
最近更新 更多