2010-03-02 11 views
18

En C# que puedo hacer:C# y F # fundición - en concreto el 'como' palabra clave

var castValue = inputValue as Type1 

En F #, que puedo hacer:

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

Pero ninguno de ellos es el equivalente de la C# como

supongo que tengo que hacer una expresión de coincidencia por el equivalente en F #

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

¿Es esto correcto?

Respuesta

22

Hasta donde yo sé, F # no tiene ningún operador integrado equivalente a C# as, por lo que debe escribir una expresión más complicada. Como alternativa a su código usando match, también se puede utilizar if, porque el operador :? se puede utilizar en la misma forma que is en C#:

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

Por supuesto, puede escribir una función para encapsular este comportamiento (por escrito un simple función genérica que toma un Object y lo convierte en el parámetro de tipo genérico especificado):

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

Esta implementación devuelve null, por lo que requiere que el parámetro tipo tiene null como prop valor de er (alternativamente, puede usar Unchecked.defaultof<'T>, que es equivalente a default(T) en C#). Ahora puede escribir simplemente:

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

Esto funciona si el tipo es estática. ¿Alguna idea de qué hacer si el tipo está definido en tiempo de ejecución? Estoy buscando un equivalente F # de http://stackoverflow.com/a/19068042/23059. –

6

Usted puede crear su propio operador para realizar esta acción. Esto es virtualmente idéntico al ejemplo de Tomás, pero muestra una forma ligeramente diferente de llamarlo. Aquí hay un ejemplo:

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

Yo usaría un patrón activo. Este es el que yo uso:

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

aquí es una muestra de cómo se 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

Esto es innecesario ... como las notas de pregunta originales, la coincidencia de patrón F # tiene esto incorporado. Puede '| :? int como i -> i'. –

+0

es funcionalmente diferente de usar '| :? 'como sugiere @DanFitch? – Maslow

+1

encontró una diferencia muy útil. puedes hacer una subcoincidencia posterior al reparto sin una cláusula when. 'function | As (Algunos verdaderos) ->() | _ ->() 'por ejemplo – Maslow

Cuestiones relacionadas