Приведение типов C# и F#, в частности ключевое слово as.

StackOverflow https://stackoverflow.com/questions/2361851

  •  23-09-2019
  •  | 
  •  

Вопрос

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

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

Это верно?

Это было полезно?

Решение

Насколько мне известно, в F# нет встроенного оператора, эквивалентного C#. as поэтому вам нужно написать более сложное выражение.В качестве альтернативы вашему коду, используя match, вы также можете использовать if, поскольку оператор :? можно использовать так же, как 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 как правильное значение (в качестве альтернативы вы можете использовать Unchecked.defaultof<'T>, что эквивалентно default(T) в С#).Теперь вы можете написать просто:

let res = castAs<Type1>(inputValue)

Другие советы

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

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

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

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

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

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

Это верно?

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top