反映 F# Discriminated Union 时的奇怪行为
Strange behaviour when reflecting over F# Discriminated Union
以下代码可以正确编译和运行:
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 时出错:-
- 没有重载匹配方法 'MakeUnion' [ VS IDE ]
- 错误 FS0001:此表达式应具有类型
整数
但这里有类型
字符串 [ 如果我手动执行代码,则在 FSI 内 ]
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" |])
即使您使用完整的命名空间作为前缀。
以下代码可以正确编译和运行:
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 时出错:-
- 没有重载匹配方法 'MakeUnion' [ VS IDE ]
- 错误 FS0001:此表达式应具有类型
整数
但这里有类型 字符串 [ 如果我手动执行代码,则在 FSI 内 ]
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" |])
即使您使用完整的命名空间作为前缀。