问题描述
这有效
open System
let f = Action(fun () -> Unchecked.defaultof<_>)
但是这个
let f = System.Action(fun () -> Unchecked.defaultof<_>)
产生编译错误
我知道我可以通过添加类型参数占位符(System.Action<_>(...)
)来解决此问题,但是知道为什么它们的行为有所不同吗?
I know I can fix it by adding a type parameter placeholder (System.Action<_>(...)
), but any idea why they behave differently?
在规范的第14.1.9节中找到了这一点:
Found this in the spec, section 14.1.9:
- 将类型添加到 TypeNames 表中.如果该类型具有CLI拼写的通用名称,例如
List'1
,则在List
和List'1
下都将添加一个条目.
- Add the type to the TypeNames table. If the type has a CLI-mangled generic name such as
List'1
then an entry is added under bothList
andList'1
.
此行为是否已针对完全限定的类型(具有省略的类型参数)进行了复制?看来并非如此.
Is this behavior replicated for fully-qualified types (with omitted type parameters)? It doesn't appear so.
推荐答案
我同意@James的说法,这与Connect上提交的错误有关,但我认为情况稍有不同.无论如何,我认为这不是预期的行为.您能否将其报告给 microsoft 点 com 上的 fsbugs ?
I agree with @James that this is related to the bug submitted on Connect, but I think it is a slightly different case. Anyway, I think this is not the intended behaviour. Could you report it to fsbugs at microsoft dot com?
无论如何-我进行了一些调试,这是我到目前为止发现的内容:
Anyway - I did some debugging and here is what I found so far:
似乎编译器使用不同的代码路径来解析名称Action
和名称System.Action
.当解析另一个时,它会在所有加载的模块(即程序集)中搜索名为System.Action
的类型(请参见 nameres.fs
文件(开源版本).
It seems that the compiler uses different code paths to resolve the name Action
and the name System.Action
. When resolving the other, it searches all loaded modules (i.e. assemblies) for a type named System.Action
(see ResolveLongIndentAsModuleOrNamespaceThen
function in the nameres.fs
file of the open-source release).
这将找到Action
的两个定义(在mscorlib
中一个,在System.Core
中另一个).我认为问题出在以下事实:名称解析只是对结果进行迭代-它找到第一个(来自System.Core
),没有可用的重载(因为它的范围从Action<_,_,_,_,_>
到具有大约15个类型参数).找到此类型后,它将报告错误,甚至没有查看是否有其他类型(在另一个程序集中)可以使用.
This finds the two definitions of Action
(one in mscorlib
and another in System.Core
). I think the issue comes from the fact that the name resolution simply iterates over the results - it finds the first one (from System.Core
), which doesn't have a usable overload (because it ranges from Action<_,_,_,_,_>
to a version with about 15 type parameters). After finding this type, it reports an error without even looking whether there is another type (in another assembly) that could be used.
如果您不引用系统程序集,则F#编译器可以很好地解决重载问题.在不带参数的情况下运行编译器会引用默认的程序集,因此无法正常工作:
If you don't reference system assemblies, then the F# compiler resolves the overload just fine. Running the compiler without parameters references the default assembly set, so this doesn't work:
fsc test.fs
但是如果我添加--noframework
标志,那么它将编译而不会出现问题:
but if I add the --noframework
flag, then it compiles without issues:
fsc --noframework test.fs
这篇关于完全合格的名称,带有导入声明的不合格名称以不同的方式解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!