当值为"无"时动态确定选项的类型

Ole*_*nov 5 f# optional

动态获取Option类型存在一些困难.假设我有一个功能:

let printType x =
   if (box x) = null then printfn "the type is 'null'"
   else printfn "the type is %A" (x.GetType())
Run Code Online (Sandbox Code Playgroud)

我们在这里有输出:

printType 3          // the type is System.Int32
printType (Some(3))  // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Int32]
printType None       // the type is null
printType null       // the type is null
Run Code Online (Sandbox Code Playgroud)

获取表达式的类型时,如何区分None和null?

Tom*_*cek 7

在运行时,选项None值表示为null,因此您无法确定其运行时类型.但是,您可以编写一个通用函数来打印选项的静态类型:

let printType (x:'T option) =
  printfn "Static type is: %s" (typeof<'T>.Name)
Run Code Online (Sandbox Code Playgroud)

根据您的需要,这可能会或可能不会满足您的需求.

printType (None : int option)     // Int32
printType (None : string option)  // String 
printType None                    // Object (the default used by the inference)
Run Code Online (Sandbox Code Playgroud)

编辑如果你想能够在任何参数上调用函数,你可以 typeof<'T>像我的例子中一样使用Matthew的解决方案中的其余逻辑.以下内容与Matthew的代码片段完全相同(但它没有正当理由创建引号):

let printType (x:'T) =
  let typeOfX = typeof<'T>
  if not <| FSharpType.IsUnion(typeOfX) && (box x) = null then 
    printfn "Static type is %s, but the value is 'null'" typeOfX.Name
  else 
    printfn "Static type is %s and value is not 'null'" typeOfX.Name
Run Code Online (Sandbox Code Playgroud)


Mat*_*igh 3

编辑: 不需要代码引用,可以使用 typeof 代替,请参阅@Tomas Petricek的答案

您可以使用代码引用从 None 获取类型

open Microsoft.FSharp.Reflection

let printType x = 
    let typeOfX = <@ x @>.Type

    if not <| FSharpType.IsUnion(typeOfX) && (box x) = null then 
        printfn "the type is 'null'"
    else 
        printfn "the type is %A" typeOfX
Run Code Online (Sandbox Code Playgroud)

您的输入:

printType 3          // the type is System.Int32
printType (Some(3))  // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Int32]
printType None       // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Object]
printType null       // the type is 'null'
Run Code Online (Sandbox Code Playgroud)