C # и F # приведение - в частности, ключевое слово as - PullRequest
25 голосов
/ 02 марта 2010

В C # я могу сделать:

var castValue = inputValue as Type1

В F # я могу сделать:

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

Но ни один из них не является эквивалентом ключевого слова C # as.

Полагаю, мне нужно сделать выражение соответствия для эквивалента в F #

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

Это правильно?

Ответы [ 5 ]

26 голосов
/ 02 марта 2010

Насколько я знаю, в F # нет встроенного оператора, эквивалентного C # as, поэтому вам нужно написать более сложное выражение.В качестве альтернативы вашему коду, использующему match, вы также можете использовать if, поскольку оператор :? можно использовать так же, как is в C #:

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 в качестве правильного значения (в качестве альтернативы вы можете использовать Unchecked.defaultof<'T>, что эквивалентно default(T) в C #).Теперь вы можете написать просто:

let res = castAs<Type1>(inputValue)
11 голосов
/ 11 августа 2014

Я бы использовал активный шаблон. Вот тот, который я использую:

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
5 голосов
/ 02 марта 2010

Вы можете создать свой собственный оператор для этого. Это практически идентично примеру Томаса, но показывает немного другой способ его назвать. Вот пример:

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
2 голосов
/ 02 марта 2010
1 голос
/ 18 апреля 2018

Полагаю, мне нужно сделать выражение соответствия для эквивалента в F #

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

Это правильно?

Да, это правильно. (Ваш собственный ответ лучше, чем остальные ответы на мой взгляд.)

...