2010-03-02 31 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