在F#中添加额外的方法作为类型扩展

时间:2012-11-16 09:24:14

标签: f# extension-methods

我有一个已经实施.Item方法的.Net库,例如

namespace Library2
type A() = 
    member m.Item with get(a: string) =   printfn "get a string"
    member m.Item with get(a: int) =   printfn "simple slice"

在使用此库的代码中,我想添加一个同名的额外方法(因此它是optional extensions):

#r @"Library2.dll"
open Library2
type A with
    member m.Item with get(a: bool) =
        printfn "get a bool"

以下示例的最后一行无法编译:

let a = new A()
a.["good"]    
a.[10]
a.[true]

F# doc说:

  

扩展方法不能是虚方法或抽象方法。他们能   重载其他同名的方法,但编译器给出   在呼吁模糊的情况下,优先考虑非扩展方法。

这意味着我无法使用相同的类型签名扩展.ToString/.GetHashCode,但在这里我使用了不同的类型签名。为什么新方法无法扩展?

3 个答案:

答案 0 :(得分:0)

我认为,问题是由事实扩展方法实现如下(C#):

public static class MyModule
{
    public static void Item(this A a, bool b)
    {
        // whatever
    }
}

编译器正在寻找.Item(...)方法,在原始的Library2.A类中找到它,并且无法搜索任何扩展方法。

请注意,如果所有 .Item(...)重载都是扩展方法,那么一切正常:

module Library2 =
    type A() = 
        member m.dummy = ()

open Library2
type A with
    member m.Item with get(a: string) =   printfn "get a string"
    member m.Item with get(a: int) =   printfn "simple slice"
    member m.Item with get(a: bool) = printfn "get a bool"

答案 1 :(得分:0)

这似乎是编译器中的一个错误。扩展方法就在那里,当你放弃索引器带来的漂亮的语法糖时可以调用它,即这样可行:

库:

namespace TestLibrary

type A() = 
    member m.Item with get(a: string) = "string"
    member m.Item with get(a: int)    = "int"

主:

open TestLibrary

type A with
    member m.Item with get(a: bool) = "bool"

[<EntryPoint>]
let main argv = 
    let a = new A()
    printfn "%s" (a.get_Item "a")
    printfn "%s" (a.get_Item 1)
    printfn "%s" (a.get_Item true)
    System.Console.ReadLine() |> ignore
    0 

我的第一个直觉是索引器不能将unit作为返回类型,但这并不是问题所在。

答案 2 :(得分:0)

奇怪的是,我在LinqPad中创建了类似的东西,它按预期工作。

module ModuleA =

    type A() = 
        member m.Item with get(a: string) = printfn "get a string"
        member m.Item with get(a: int) = printfn "simple slice"

module ModuleB = 
    open ModuleA

    type A with
        member m.Item with get(a: bool) = printfn "get a bool"

open ModuleB

let a = new ModuleA.A()
a.["good"]    
a.[10]
a.[true]

// get a string
// simple slice
// get a bool