【问题标题】:reflection and pattern matching in F#F# 中的反射和模式匹配
【发布时间】:2015-07-02 06:29:52
【问题描述】:

我正在尝试在 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))

【问题讨论】:

  • 它到底是怎么不起作用的?还有,它是如何使用反射的?
  • 它只是不属于任何模式。
  • 当你问问题时,永远不要写 - “它不起作用”。清楚地解释问题和期望的行为

标签: f#


【解决方案1】:

无需重新发明轮子,使用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

【讨论】:

    【解决方案2】:

    由于t总是Type 值,它永远不会属于intbytedecimal 等类型。这就是函数总是引发异常的原因;那些其他的匹配永远不会是真的。

    相反,您必须将ttypeof&lt;int&gt;typeof&lt;byte&gt; 等进行比较。但是,您不能为此使用常量模式,因为typeof&lt;int&gt;typeof&lt;byte&gt; 等不是常量。

    相反,您可以使用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 后面,但我个人认为这不值得。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      • 1970-01-01
      • 1970-01-01
      • 2015-01-25
      • 1970-01-01
      相关资源
      最近更新 更多