特定泛型类型的扩展方法

时间:2009-10-07 13:15:52

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

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

我想做的事情如下:

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

然而它给了我编译器错误(加下int关键字的下划线):

  

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

以下 工作,但它没有将泛型类型参数专门绑定到int,如我所愿:

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

有没有办法在F#中实现这个目标 - 我可能只是使用了错误的语法?如果没有,我会很感激,如果有人可以建议一个解决方法,可能在某处使用类型约束。

4 个答案:

答案 0 :(得分:8)

现在可以在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())

答案 1 :(得分:7)

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

答案 2 :(得分:0)

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

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

嗯...

答案 3 :(得分:0)

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

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

[<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