C#和F#cast - 特别是'as'关键字

Nic*_*ell 27 c# f# c#-to-f#

在C#我可以这样做:

var castValue = inputValue as Type1
Run Code Online (Sandbox Code Playgroud)

在F#中,我可以这样做:

let staticValue = inputValue :> Type1
let dynamicValue = inputValue :?> Type1
Run Code Online (Sandbox Code Playgroud)

但它们都不等同于C#的关键字as.

我想我需要为F#中的等价物做一个匹配表达式

match inputValue with
| :? Type1 as type1Value -> type1Value
| _ -> null
Run Code Online (Sandbox Code Playgroud)

它是否正确?

Tom*_*cek 28

据我所知,F#没有任何与C#等效的内置运算符,as因此您需要编写一些更复杂的表达式.match您也可以使用代码,也可以使用if,因为运算符:?可以像is在C#中一样使用:

let res = if (inputValue :? Type1) then inputValue :?> Type1 else null
Run Code Online (Sandbox Code Playgroud)

您当然可以编写一个函数来封装此行为(通过编写一个简单的泛型函数来获取Object并将其强制转换为指定的泛型类型参数):

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

此实现返回null,因此它要求type参数具有null适当的值(或者,您可以使用Unchecked.defaultof<'T>,这相当于default(T)在C#中).现在你可以写:

let res = castAs<Type1>(inputValue)
Run Code Online (Sandbox Code Playgroud)


Tah*_*san 11

我会使用活动模式.这是我使用的那个:

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

以下是一个示例用法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
Run Code Online (Sandbox Code Playgroud)

  • 这是不必要的...正如原始问题所述,F#模式匹配内置了这个.你可以`| :?int as i - > i`. (3认同)
  • 发现了一个非常有用的区别.你可以在没有when子句的情况下进行Post-cast子匹配.`function | As(Some true) - >()| _ - >()`例如 (3认同)

kvb*_*kvb 5

您可以创建自己的运算符来执行此操作.这实际上与Tomas的例子完全相同,但显示了一种稍微不同的方式来调用它.这是一个例子:

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
Run Code Online (Sandbox Code Playgroud)