F# 中的反射和模式匹配
reflection and pattern matching in F#
我正在尝试在给定 F# 类型的情况下创建原始值。代码如下所示,但不起作用。我将不胜感激所有帮助并提前致谢。
open System
let getvalue (t: Type) (v: string) : obj =
match box t with
| :? int -> let r = (int) v
box r
| :? byte -> let r = (byte) v
box r
| :? sbyte -> let r = (sbyte) v
box r
| :? int16 -> let r = (int16) v
box r
| :? uint32 -> let r = (uint32) v
box r
| :? int64 -> let r = (int64) v
box r
| :? uint64 -> let r = (uint64) v
box r
| :? double -> let r = (double) v
box r
| :? float32 -> let r = (float32) v
box r
| :? decimal -> let r = (decimal) v
box r
| :? char -> let r = (char) v
box r
| :? string -> v :> obj
| _ ->
let s = sprintf "Error unknown type %A" t
raise (ApplicationException(s))
因为 t
总是 一个 Type
值,它从不 是 int
、byte
、decimal
等。这就是函数总是引发异常的原因;那些其他比赛永远不会是真的。
相反,您必须将 t
与 typeof<int>
、typeof<byte>
等进行比较。但是,您不能使用 常量模式 因为 typeof<int>
、typeof<byte>
等不是常量。
相反,您可以使用 if .. elif .. else
表达式:
open System
let getValue (t: Type) (v: string) : obj =
if t = typeof<int> then box ((int) v)
elif t = typeof<byte> then box ((byte) v)
elif t = typeof<sbyte> then box ((sbyte) v)
elif t = typeof<int16> then box ((int16) v)
elif t = typeof<uint32> then box ((uint32) v)
elif t = typeof<int64> then box ((int64) v)
elif t = typeof<uint64> then box ((uint64) v)
elif t = typeof<double> then box ((double) v)
elif t = typeof<float32> then box ((float32) v)
elif t = typeof<decimal> then box ((decimal) v)
elif t = typeof<char> then box ((char) v)
elif t = typeof<string> then v :> obj
else
let s = sprintf "Error unknown type %A" t
raise (ApplicationException(s))
如果您真的想要使用模式匹配,您可以考虑将其隐藏在active pattern 后面,但我个人认为这不值得。
不用重新发明轮子,用Convert.ChangeType.
如果您愿意,可以围绕它编写一个包装器,让编译器自动确定类型。
let inline getValue<'a> (s:string) = // limit to string only if desired
System.Convert.ChangeType(s, typeof<'a>) :?> 'a
let x = getValue "1" + 1.2 // no need to explicitly state "float" anywhere here
printfn "%A" x // 2.2
我正在尝试在给定 F# 类型的情况下创建原始值。代码如下所示,但不起作用。我将不胜感激所有帮助并提前致谢。
open System
let getvalue (t: Type) (v: string) : obj =
match box t with
| :? int -> let r = (int) v
box r
| :? byte -> let r = (byte) v
box r
| :? sbyte -> let r = (sbyte) v
box r
| :? int16 -> let r = (int16) v
box r
| :? uint32 -> let r = (uint32) v
box r
| :? int64 -> let r = (int64) v
box r
| :? uint64 -> let r = (uint64) v
box r
| :? double -> let r = (double) v
box r
| :? float32 -> let r = (float32) v
box r
| :? decimal -> let r = (decimal) v
box r
| :? char -> let r = (char) v
box r
| :? string -> v :> obj
| _ ->
let s = sprintf "Error unknown type %A" t
raise (ApplicationException(s))
因为 t
总是 一个 Type
值,它从不 是 int
、byte
、decimal
等。这就是函数总是引发异常的原因;那些其他比赛永远不会是真的。
相反,您必须将 t
与 typeof<int>
、typeof<byte>
等进行比较。但是,您不能使用 常量模式 因为 typeof<int>
、typeof<byte>
等不是常量。
相反,您可以使用 if .. elif .. else
表达式:
open System
let getValue (t: Type) (v: string) : obj =
if t = typeof<int> then box ((int) v)
elif t = typeof<byte> then box ((byte) v)
elif t = typeof<sbyte> then box ((sbyte) v)
elif t = typeof<int16> then box ((int16) v)
elif t = typeof<uint32> then box ((uint32) v)
elif t = typeof<int64> then box ((int64) v)
elif t = typeof<uint64> then box ((uint64) v)
elif t = typeof<double> then box ((double) v)
elif t = typeof<float32> then box ((float32) v)
elif t = typeof<decimal> then box ((decimal) v)
elif t = typeof<char> then box ((char) v)
elif t = typeof<string> then v :> obj
else
let s = sprintf "Error unknown type %A" t
raise (ApplicationException(s))
如果您真的想要使用模式匹配,您可以考虑将其隐藏在active pattern 后面,但我个人认为这不值得。
不用重新发明轮子,用Convert.ChangeType.
如果您愿意,可以围绕它编写一个包装器,让编译器自动确定类型。
let inline getValue<'a> (s:string) = // limit to string only if desired
System.Convert.ChangeType(s, typeof<'a>) :?> 'a
let x = getValue "1" + 1.2 // no need to explicitly state "float" anywhere here
printfn "%A" x // 2.2