动态转换为接口

Fre*_*ang 2 f#

根据帖子http://cs.hubfs.net/forums/thread/3616.aspx,我需要使用如下函数将对象强制转换为接口,我已经运行了测试,这仍然是真的,错误:?>仍然没有修复.

let cast<'a> o = (box o) :?> 'a
let ci = {  new Customer(18, Name = "fred") with
                override x.ToString() = x.Name 
            interface ITalk with
                member x.Talk() =
                    printfn "talk1111111" }

let italk = cast<ITalk> ci

if not (italk = null) then
    italk.Talk()
Run Code Online (Sandbox Code Playgroud)

是否有更优雅的方式来编写上面的代码.我想创建另一个运算符来替换:?>,但是我无法获得传递的泛型类型参数,如:?>

Joe*_*ler 6

您的cast函数的行为与C#as运算符不同 - 如果对象无法转换为指定的类型,它将抛出异常而不是返回null.因此,检查是否italk = null完成任何事情.如果你想cast在转换失败而不是抛出异常时让函数返回null,你可以像这样写:

let cast<'a when 'a : null> o =
    match box o with
    | :? 'a as output -> output
    | _ -> null
Run Code Online (Sandbox Code Playgroud)

但是,这只适用于可空类型,它不包括结构或(默认情况下)F#类型.我可能会按原样保留您的cast功能,并tryCast使用选项.

let tryCast<'a> o =
    match box o with
    | :? 'a as output -> Some output
    | _ -> None
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

ci |> tryCast<ITalk> |> Option.iter (fun it -> it.Talk())
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Option.iter取代您的空测试.