动态获取Option类型存在一些困难。假设我有一个功能:
let printType x =
if (box x) = null then printfn "the type is 'null'"
else printfn "the type is %A" (x.GetType())
我们在这里有输出:
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
获取表达式的类型时,如何区分None和null?
答案 0 :(得分:7)
在运行时,选项None
值表示为null
,因此您无法确定其运行时类型。但是,您可以编写一个通用函数来打印选项的静态类型:
let printType (x:'T option) =
printfn "Static type is: %s" (typeof<'T>.Name)
根据您的需要,这可能会或可能不会满足您的需求。
printType (None : int option) // Int32
printType (None : string option) // String
printType None // Object (the default used by the inference)
编辑如果您希望能够在任何参数上调用该函数,您可以像我的示例中一样使用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
答案 1 :(得分:3)
编辑: 不需要代码报价,可以使用typeof,请参阅@Tomas Petricek的回答
您可以使用代码报价从无
中获取类型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
您的意见:
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'
答案 2 :(得分:0)
这在实现解释器时可能是一个常见问题。要添加到上述解决方案,您还可以执行以下操作:
open System
type TagObj (obj : obj, t : Type) =
member __.Obj = obj
member __.Type = t
and TagObj<'T>(value : 'T) =
inherit TagObj(value, typeof<'T>)
member __.Value = value
override __.ToString() = sprintf "%O" value
let mkTag x = TagObj<_>(x) :> TagObj
// examples
let t = mkTag (None : int option)
let t' = mkTag ()
t.Obj = t'.Obj // true
t.Type = t'.Type // false
这大致是如何在引文中表示常量值。