Приведение типов C# и F#, в частности ключевое слово as.
Вопрос
В С# я могу сделать:
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
Да;смотрите также
Как этот код C# выглядит в F#?(Первая часть:выражения и утверждения)
Думаю, мне нужно сделать выражение соответствия для эквивалента в F#.
match inputValue with | :? Type1 as type1Value -> type1Value | _ -> null
Это верно?
Да, это правильно.(На мой взгляд, ваш собственный ответ лучше, чем остальные ответы.)