Dynamic cast to Interface
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()
精彩评论