具有通用约束的类型扩展不会引发错误,也不会执行预期的操作

Type extensions with a generic constraint not raising an error, nor doing what might be expected

考虑以下使用 F# 4.0、.NET 4.6 的代码片段:

type X<'T> = Y of 'T

type XS = X<string>
type XI = X<int>

type X<'T when 'T :> string> with
    static member X = 2
    static member take (s: 'T) = s

[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module XS =
    let foo = 10
    let create s = XS.Y s
    let test = XI.take 2    // expected only string allowed, XI.take should not exist

我希望类型扩展 type X<'T when 'T :> string> with 得到尊重(在这种情况下这意味着错误,因为 string 是密封的,或者将 'T 限制为 string),或引发语法错误。

此外,我还可以使用以下语法,这在普通类型定义中会是语法错误(没有with):

type X<'T> when 'T :> string with
    static member X = 2
    static member take (s: 'T) = s

我的猜测是限制在扩展中被简单地忽略了。这是设计使然吗?或者它应该有效吗?如果有效,如何?

我在对类型扩展进行一些试验时想到了这一切,想知道我是否可以创建一组仅适用于特定具体类型或进一步受限具体类型的特定方法(也可以完成的事情通过继承,我知道)。

我认为编译器应该拒绝你的代码,但这里有一些观察结果:

  1. 请注意,如果您使用 "extrinsic" 扩展(例如,通过将定义和扩展放在不同的模块中 - 请参阅 Type Extensions),行为会有所不同 - 在那里,编译器将扩​​展标记为错误。
  2. 如果您想要 instance 扩展方法只显示类型参数的某些具体值,那么您可以使用 C# 风格的扩展方法(这在上面的 link 中也有解释)。但是,由于 C# 不支持 static 扩展成员,因此无法将此技巧应用于您的方案。