2010-03-02 8 views
18

In C# kann ich tun:C# und F # Gießen - speziell die 'als' Schlüsselwort

var castValue = inputValue as Type1 

In F #, was ich tun kann:

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

Aber keiner von ihnen ist das Äquivalent der C# als

ich glaube, ich brauche ein Spiel Ausdruck für das Äquivalent in F # tun

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

Ist das korrekt?

Antwort

22

Soweit ich weiß, hat F # keinen integrierten Operator, der C# as entspricht, also müssen Sie etwas kompliziertere Ausdrücke schreiben. Alternativ zu Ihren Code mit match, könnten Sie auch if verwenden, da der Bediener :? kann Gebrauch in der gleichen Weise wie is in C# sein:

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

Sie können natürlich auch eine Funktion schreiben, um dieses Verhalten zu kapseln (durch Schreiben eine einfache generische Funktion, die ein Object und wirft es auf den angegebenen generischen Typparameter nimmt):

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

Diese Implementierung liefert null, so erfordert es, dass der Typ-Parameter null als Stütze hat er-Wert (alternativ könnten Sie Unchecked.defaultof<'T> verwenden, was default(T) in C# entspricht). Jetzt können Sie nur schreiben:

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

Dies funktioniert, wenn der Typ statisch ist. Irgendeine Idee, was zu tun ist, wenn der Typ zur Laufzeit definiert ist? Ich suche nach einem F # -Aquivalent von http://StackOverflow.com/a/19068042/23059. –

6

Sie können Ihren eigenen Operator erstellen, dies zu tun. Dies ist praktisch identisch mit Tomas Beispiel, zeigt aber eine etwas andere Art, es zu nennen. Hier ist ein Beispiel:

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

Ich würde ein aktives Muster verwenden. Hier ist die, die ich benutze:

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

Hier ist ein Beispiel Verwendung von 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

Das ist nicht notwendig ... wie die ursprüngliche Frage feststellt, hat F # Mustervergleich das eingebaut. Sie können '| :? int wie ich -> ich. –

+0

ist dies funktional anders als mit '| :? 'wie @DanFitch vorschlägt? – Maslow

+1

gefunden einen sehr nützlichen Unterschied. Sie können Post-Cast-Sub-Matching ohne eine WENN-Klausel durchführen. 'function | As (Some true) ->() | _ ->() 'zum Beispiel – Maslow