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

时间:2019-10-16 13:25:57

标签: c# generics f# overloading

根据通用参数,我正在努力调用按参数类型重载的方法(从C#库)

在下面的示例中,我使用了带有重载方法的F#类来说明这一点。关键是通用参数可以是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

1 个答案:

答案 0 :(得分:2)

您可以将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时,它可以工作。无论如何,您都会失去编译时的安全性。