根据帖子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()
是否有更优雅的方式来编写上述代码。我想创建另一个运算符来替换:?&gt;,但我无法获得传入的泛型类型参数,如:?&gt;
答案 0 :(得分: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
但是,这只适用于可空类型,它不包括结构或(默认情况下)F#类型。我可能会保留您的cast
功能,并制作一个使用选项的tryCast
。
let tryCast<'a> o =
match box o with
| :? 'a as output -> Some output
| _ -> None
然后你可以像这样使用它:
ci |> tryCast<ITalk> |> Option.iter (fun it -> it.Talk())
在这种情况下,Option.iter
代替您的空测试。
答案 1 :(得分:2)
模式匹配提供了一种更为惯用的方式来写这个:
match box ci with
| :? ITalk as italk -> italk.Talk()
| _ -> ()
或者,甚至:
let bci = box ci
if bci :? ITalk then (bci :?> ITalk).Talk()
我保留了以下功能,因为当我知道类型测试将保持时:
let coerce value = (box >> unbox) value
(coerce ci : ITalk).Talk()