这有效
open System
let f = Action(fun () -> Unchecked.defaultof<_>)
但是这个
let f = System.Action(fun () -> Unchecked.defaultof<_>)
产生编译错误
存在多种类型,称为“Action”,采用不同数量的通用参数。提供类型实例化以消除类型解析的歧义,例如'动作及LT; ,,_,,,_,,,_&GT;'。
我知道我可以通过添加类型参数占位符(System.Action<_>(...)
)来修复它,但是知道为什么它们的行为不同?
在规范第14.1.9节中找到了这个:
当打开模块或名称空间声明组
F
时,项目将添加到名称环境中,如下所示:
- 将类型添加到 TypeNames 表中。如果类型具有CLI错误的通用名称,例如
List'1
,则会在List
和List'1
下添加一个条目。
是否为完全限定类型(省略了类型参数)复制了此行为?它似乎不是这样。
答案 0 :(得分:4)
我同意@James这与Connect上提交的错误有关,但我认为这是一个略有不同的情况。无论如何,我认为这不是预期的行为。你可以在 microsoft dot com 上向 fsbugs 报告吗?
无论如何 - 我做了一些调试,这是我到目前为止所发现的:
编译器似乎使用不同的代码路径来解析名称Action
和名称System.Action
。解析另一个时,它会搜索所有已加载的模块(即程序集)以查找名为System.Action
的类型(请参阅开源版本nameres.fs
file中的ResolveLongIndentAsModuleOrNamespaceThen
函数)。
这会找到Action
的两个定义(mscorlib
中的一个和System.Core
中的另一个)。我认为问题来自这样一个事实:名称解析简单地遍历结果 - 它找到第一个(来自System.Core
),它没有可用的重载(因为它的范围是Action<_,_,_,_,_>
到具有约15个类型参数的版本)。找到此类型后,它会报告错误,甚至不会查看是否有其他类型(在另一个程序集中)可以使用。
如果您不引用系统程序集,那么F#编译器可以很好地解决重载问题。运行不带参数的编译器会引用默认的程序集,因此不起作用:
fsc test.fs
但是如果我添加--noframework
标志,那么它会毫无问题地编译:
fsc --noframework test.fs