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

标签 generics f# generic-constraints type-extension

考虑以下使用 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

我的猜测是,扩展上的约束被简单地忽略了。这是设计使然吗?或者它应该工作,如果是这样,如何?

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

最佳答案

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

  • 请注意,如果您使用“外部”扩展名(例如,通过将定义和扩展名放在不同的模块中 - 参见 Type Extensions ),行为会有所不同 - 在那里,编译器会将扩展名标记为错误。
  • 如果您想要的是仅针对类型参数的某些具体值显示的实例扩展方法,那么您可以使用 C# 样式的扩展方法(这也在上面的链接中进行了说明)。但是,由于 C# 不支持静态扩展成员,因此无法将此技巧应用于您的方案。
  • 关于generics - 具有通用约束的类型扩展不会引发错误,也不会执行预期的操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40011958/

    相关文章:

    f# - 无法从 F# 中查看 Excel Interop 中的某些属性

    .net - sprintf 与 String.Format 的性能

    c# - 是否可以在 C# 泛型方法中定义 "not Nullable<T>"约束?

    c# - 类级别的结构和字符串通用约束

    .NET 泛型类型约束不等式

    haskell - 为什么通用函数以特殊的方式处理列表头?

    java - 在 java 中创建一个用户定义的类,就像 Integer/String 类

    swift - 为什么我需要指定对象类型两次?

    scala - 在 Scala 中调用泛型类型的 "static function"

    f# - 在 f# 脚本中执行 c# 代码有意外行为