【问题标题】:Extension methods for specific generic types特定泛型类型的扩展方法
【发布时间】:2009-10-07 13:15:52
【问题描述】:

我正在尝试为 F# 中绑定到特定泛型类型参数的泛型类型创建各种扩展方法,但该语言似乎不允许我:

我想要做的是如下所示:

type IEnumerable<int> with
    member this.foo =
        this.ToString()

但它给了我编译器错误(在int 关键字下划线):

类型名称中有意外的标识符。预期的中缀运算符、引号或其他标记。

以下确实工作,虽然它没有像我想要的那样专门将泛型类型参数绑定到int

type IEnumerable<'a> with
    member this.foo =
        this.ToString()

有什么方法可以在 F# 中实现这一目标——我可能只是使用了错误的语法吗?如果没有,如果有人可以提出解决方法,我将不胜感激,也许在某处使用类型约束。

【问题讨论】:

    标签: generics f# extension-methods type-constraints generic-type-argument


    【解决方案1】:

    现在 F# 3.1 中提供了通用扩展方法:

    open System.Runtime.CompilerServices
    open System.Collections.Generic
    
    [<Extension>]
    type Utils () =
        [<Extension>]
        static member inline Abc(obj: IEnumerable<int>) = obj.ToString()
    
    printfn "%A" ([1..10].Abc())
    

    【讨论】:

      【解决方案2】:

      不幸的是,这在当前版本的 F# 中是不可能的。请参阅相关问题here

      【讨论】:

      • 内部 F# 错误数据库“4548:支持特定类型实例化的扩展方法”中的建议跟踪了此功能,但它不太可能在 VS2010 版本中实现。
      【解决方案3】:

      嗯,你可以使用约束——但不能使用像 int 这样的密封类型。

      type IEnumerable<'a when 'a :> InheritableType> =
      member this.Blah =
          this.ToString()
      

      嗯……

      【讨论】:

      • 感谢您的建议,但实际上,我在这里使用的是密封类型,所以不太好用。
      • 这可能与您想象的不太一样...您实际上是在定义一个新的 IEnumerable 类型 - 尝试在现有的 IEnumerable&lt;InheritableType&gt; 上调用扩展。
      【解决方案4】:

      为了帮助其他人寻找类似的解决方案,这里有一个示例,展示了如何使用具有类型约束的泛型扩展方法。在下面的示例中,有一个类型约束要求传递的类型参数公开一个默认构造函数。这是使用应用于Order 记录的[&lt;CLIMutable&gt;] 属性完成的。另外,我将方法的结果限制为传递的类型。

      为了使用扩展方法,您必须指定要使用的类型。请注意,我还在扩展通用字典接口。

      [<Extension>]
      type ExtensionMethds () = 
      
          [<Extension>]
          static member inline toObject<'T when 'T: (new: unit -> 'T)> (dic: IDictionary<string,obj>): 'T =
              let instance = new 'T()
              // todo: set properties via reflection using the dictionary passed in
              instance
      
      
      [<CLIMutable>]
      type Order = {id: int}
      
      let usage = 
          let dictionaryWithDataFromDb = dict ["id","1" :> obj] 
          let theOrder = dictionaryWithDataFromDb.toObject<Order>()
          theOrder
      

      【讨论】:

        猜你喜欢
        • 2014-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多