【问题标题】:Strange behaviour when reflecting over F# Discriminated Union反射 F# 可区分联合时的奇怪行为
【发布时间】:2016-01-12 11:51:07
【问题描述】:

以下代码可以正确编译运行:

type FooUnion = MyCase of int * string

FSharp.Reflection.FSharpType.GetUnionCases(typeof<FooUnion>)
|> Array.tryFind(fun a -> a.Name = "MyCase")
|> Option.map(fun d -> FSharp.Reflection.FSharpValue.MakeUnion(d, [| 1; "test" |]))
|> Option.bind(function | :? FooUnion as s -> Some s | _ -> None)

但是,如果我删除完全限定的 FSharp.Reflection 并将其移至 open 语句,则代码不再编译:-

open FSharp.Reflection

type FooUnion = MyCase of int * string

FSharpType.GetUnionCases(typeof<FooUnion>)
|> Array.tryFind(fun a -> a.Name = "MyCase")
|> Option.map(fun d -> FSharpValue.MakeUnion(d, [| 1; "test" |]))
|> Option.bind(function | :? FooUnion as s -> Some s | _ -> None)

调用 MakeUnion 时出现错误:-

  1. 没有重载匹配方法“MakeUnion”[在 VS IDE 中]
  2. 错误 FS0001:此表达式应具有类型 整数
    但这里有类型 string [如果我手动执行代码,在 FSI 中]

【问题讨论】:

    标签: reflection f# discriminated-union


    【解决方案1】:

    FSharpValue 类型包含一个 MakeUnion 方法:

    static member MakeUnion : unionCase:Reflection.UnionCaseInfo * args:obj [] * ?bindingFlags:System.Reflection.BindingFlags -> obj
    

    但 FSharp.Reflection 命名空间包含一个签名稍有不同的扩展方法。

    FSharp 编译器只有在没有重载时才会隐式地装箱 args 数组的内容,所以打开命名空间需要将代码改为:

    FSharpValue.MakeUnion(d, [| box 1; box "test" |])
    

    即使您使用完整的命名空间作为前缀。

    【讨论】:

    • 扩展方法!啊!
    猜你喜欢
    • 1970-01-01
    • 2011-11-19
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 2016-09-10
    • 1970-01-01
    相关资源
    最近更新 更多