F#中如何调用参数类型重载的方法?

How to call methods overloaded by parameter type in F#?

根据泛型参数,我正在努力调用一个由参数类型重载的方法(来自 C# 库)

在下面的示例中,我使用了带有重载方法的 F# class 来说明这一点。关键是泛型参数可以是 struct 或引用类型,它可以是相关参数类型之一的派生类型(我在这里使用 StreamWriter 来说明)。

open System.IO

type MyClass() =
    member this.Method(n: int) = sprintf "Integer %i" n
    member this.Method(s: string) = sprintf "String %s" s
    member this.Method(w: TextWriter) = sprintf "Some kind of text writer"

let passValueToCorrectMethod (c: MyClass) (value: 'a) : string =
    match value with
    | :? int as n -> c.Method(n) // ERROR: Runtime type tests are not allowed on some types
    | :? string as s -> c.Method(s)
    | :? TextWriter as w -> c.Method(w)

// what I want to be able to do with it
let c = MyClass()
let sw = new StreamWriter("C:\temp\blah")

let result1 = passValueToCorrectMethod c 5
let result2 = passValueToCorrectMethod c "hi"
let result3 = passValueToCorrectMethod c sw

您可以将 value: 'a 更改为 value: obj(如@Charles Mager 所建议)并可选择添加一个包罗万象的案例:_ -> failwith "No overload"。或者,如果你愿意使用反射:

let passValueToCorrectMethod (c: MyClass) (value: 'a) : string =
    let valueType = typeof<'a>
    let mi = c.GetType().GetMethod("Method", BindingFlags.Instance ||| BindingFlags.Public, null, [| valueType |], null)
    if isNull mi then
        failwithf "No overload for %s" valueType.Name
    else    
        mi.Invoke(c, [| value |]) |> string

// what you'll be able to do with it
let c = MyClass()
let sw = new StreamWriter(".\temp.txt")

passValueToCorrectMethod c sw // Some kind of text writer
passValueToCorrectMethod c () // Runtime Exception: No overload for Unit

这种方式在添加/删除 Method 而不更改 passValueToCorrectMethod 时有效。不管怎样,你失去了编译时的安全性。