开发者

Dynamic cast to Interface

开发者 https://www.devze.com 2023-03-20 05:58 出处:网络
According to the post http://cs.hubfs开发者_Go百科.net/forums/thread/3616.aspx, I need to use a function like the following to cast an object to an interface, I have run a test, this is still true, th

According to the post http://cs.hubfs开发者_Go百科.net/forums/thread/3616.aspx, I need to use a function like the following to cast an object to an interface, I have run a test, this is still true, the bug of :?> is still not fixed.

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()

Is there a more elegant way to write the above code. I am thinking to create another operator to replace :?>, but I can not get the generic type parameter passed in like the :?>


Your cast function does not behave like the C# as operator - if the object can't be cast to the specified type, it will throw an exception rather than returning null. Therefore, checking to see if italk = null accomplishes nothing. If you want to make the cast function return null when the cast fails instead of throwing an exception, you could write it like this:

let cast<'a when 'a : null> o =
    match box o with
    | :? 'a as output -> output
    | _ -> null

However, this will only work on nullable types, which does not include structs or (by default) F# types. I might leave your cast function the way it is, and make a tryCast that uses options.

let tryCast<'a> o =
    match box o with
    | :? 'a as output -> Some output
    | _ -> None

Then you could use it like this:

ci |> tryCast<ITalk> |> Option.iter (fun it -> it.Talk())

In this case, Option.iter takes the place of your null test.


Pattern matching provides a more idiomatic way to write this:

match box ci with
| :? ITalk as italk -> italk.Talk()
| _ -> ()

Or, even:

let bci = box ci
if bci :? ITalk then (bci :?> ITalk).Talk()

I keep a function like the following around, for when I know the type test will hold:

let coerce value = (box >> unbox) value

(coerce ci : ITalk).Talk()
0

精彩评论

暂无评论...
验证码 换一张
取 消