2010-03-02 13 views
18

在C#中我可以这样做:C#和F#铸 - 特别是 '为' 关键字

var castValue = inputValue as Type1 

在F#中,我可以这样做:

let staticValue = inputValue :> Type1 
let dynamicValue = inputValue :?> Type1 

但它们都不是的等效C#作为

我想我需要在F#相当于做一个匹配表达式

match inputValue with 
| :? Type1 as type1Value -> type1Value 
| _ -> null 

这是正确的吗?

回答

22

据我所知,F#没有任何相当于C#的内置运算符as所以你需要写一些更复杂的表达式。可选择使用match你的代码,你也可以使用if,因为操作人员:?可以在C#是相同的方式用作is

let res = if (inputValue :? Type1) then inputValue :?> Type1 else null 

当然,你可以写一个函数封装这个行为(通过写一个简单的泛型函数,它接受一个Object并将它转换到指定的泛型类型参数):

let castAs<'T when 'T : null> (o:obj) = 
    match o with 
    | :? 'T as res -> res 
    | _ -> null 

此实现返回null,所以它需要的类型参数有null做道具er值(或者,您可以使用Unchecked.defaultof<'T>,这相当于C#中的default(T))。现在你可以只写:

let res = castAs<Type1>(inputValue) 
+0

这工作如果类型是静态的。任何想法如果类型是在运行时定义的怎么办?我正在寻找一个F#相当于http://stackoverflow.com/a/19068042/23059。 – 2015-12-28 03:12:19

6

您可以创建自己的运营商做到这一点。这与Tomas的例子几乎完全相同,但显示了一种稍微不同的称呼方式。这里有一个例子:

let (~~) (x:obj) = 
    match x with 
    | :? 't as t -> t //' 
    | _ -> null 

let o1 = "test" 
let o2 = 2 
let s1 = (~~o1 : string) // s1 = "test" 
let s2 = (~~o2 : string) // s2 = null 
10

我会使用一个活动模式。下面是我使用的一个:

let (|As|_|) (p:'T) : 'U option = 
    let p = p :> obj 
    if p :? 'U then Some (p :?> 'U) else None 

这里是As样例用法:

let handleType x = 
    match x with 
    | As (x:int) -> printfn "is integer: %d" x 
    | As (s:string) -> printfn "is string: %s" s 
    | _ -> printfn "Is neither integer nor string" 

// test 'handleType' 
handleType 1 
handleType "tahir" 
handleType 2. 
let stringAsObj = "tahir" :> obj 
handleType stringAsObj 
+2

这是不必要的......正如原始问题所指出的那样,F#模式匹配具有内置的功能。 :? int as i - > i'。 – 2016-08-09 22:06:40

+0

在功能上与使用'|不同:?@DanFitch暗示? – Maslow 2016-09-21 14:15:59

+1

发现一个主要有用的区别。您可以在没有when子句的情况下进行Post-cast子匹配。 'function | As(Some true) - >()| _ - >()'例如 – Maslow 2018-02-22 19:06:57