Types obj[]和string[]作为参数

Types obj[]和string[]作为参数,types,casting,f#,type-conversion,Types,Casting,F#,Type Conversion,我使用的是Microsoft.FSharp.Reflection.FSharpValue.MakeUnion,这需要Reflection.UnionCaseInfo和obj[](可以为空)作为参数 然而,我得到了一份工作 类型不匹配。使用字符串[]函数的结果调用时,类型“obj”与类型“string”不匹配,应为obj[],但给定字符串[] 我能为这种情况创建的最简单的例子如下(我有一个围绕它的测试,但它没有编译,因为有一行标记为!!) let one (a:obj[]) = a |> A

我使用的是
Microsoft.FSharp.Reflection.FSharpValue.MakeUnion
,这需要
Reflection.UnionCaseInfo
obj[]
(可以为空)作为参数

然而,我得到了一份工作
类型不匹配。使用
字符串[]函数的结果调用时,类型“obj”与类型“string”不匹配,应为obj[],但给定字符串[]

我能为这种情况创建的最简单的例子如下(我有一个围绕它的测试,但它没有编译,因为有一行标记为
!!

let one (a:obj[]) = a |> Array.map (fun o->printfn "%A" o) |> ignore
one [|"a";"b";"c"|] // OK!
let str = [|"a";"b";"c"|] //the equivalent of my function return
one str//!!Type mismatch.
我不确定我是否打算将string[]转换成obj[],或者……嗯,如果我只是做了一些我不知道的错误

编辑:实际问题如下所述

这就是我曾经解决的问题:有没有更好的方法

作为参考

我也试过这个

但这也给了我一个错误:

如果我不执行
数组.map
,则在函数的最后一行键入不匹配


如果定义变量以保留对象数组,则还可以使用类型注释,F#将自动向上投射字符串到对象:

let values : obj[] = [|"a";"b";"c"|]
更一般地说,如果编译器在找到表达式之前知道目标类型(它从左向右看),那么它将自动构建对象数组,即使文本包含字符串。这也是您所问的函数调用的情况


但是,一旦您创建了类型为
string[]
,您就必须以某种方式将其转换为
obj[]

我认为您当前的方法很好;有时我发现类似于
[| for str in…->box str]
的东西比
..>Array.map(fun str->box str
但是你的里程数可能会有所不同。至于你为什么会遇到这种情况,这里有两个微妙的问题

正如Phil Trelford的评论所暗示的那样,.NET类型系统允许将
string[]
视为
obj[]
(尽管从F#开始这样做需要上下转换,即使.NET类型系统没有那么严格)。在我看来,这种类型系统“功能”这是一个令人憎恶的问题,我通常会避免它,即使在这种情况下它可能是安全的(对于数组协方差的不可取性的一致意见,请参见和)


因此,一般来说,
string[]
不会被编译器视为
obj[]
。那么,当您传入
[|“a”;“b”;“c”|时,为什么一切都正常呢
?这里的答案是,在数组文本的特定情况下,编译器允许数组表达式的类型为每个元素类型的超类型,前提是可以推断出这种超类型(例如,因为它被另一个方法的签名约束为
obj[]
)。但是,这仅适用于数组文字(即
[|e1;e2;…|]
形式的表达式)。

谢谢。我已尝试在返回数组的函数上使用此符号(编辑问题以反映)但这也给了我同样的例外。我没有将数组作为
let
,它是从模式匹配中管道化出来的。@phillip trelford-“您也可以将one函数更改为接受任何对象数组,例如let one(a:#obj[])”(与我的“答案”一起删除-恢复为有价值)您可以创建自己的MakeUnion函数,该函数调用FSharpValue。MakeUnionTomas的答案可能是我的默认答案,您也可以缩短
(fun s->s:>obj)
buildArgs
的定义不提供任何类型不匹配-它返回一个字符串array@CodeBeard
buildArgs
最短但可能最邪恶的解决方法是
(content |>split“”)|>box |>unbox
这很清楚-谢谢。总的来说,我觉得类型系统“任由摆布”,我不得不解决它,这有点错误。我理解。但请记住,从语义上讲,字符串数组实际上不是对象数组(尽管这可能有点不直观)。我相信如果.NET的设计者能够回到过去,他们会引入ReadOnlyArray类型,并在整个框架的许多地方使用它来代替常规数组(字符串ReadOnlyArray确实可以安全地被视为对象ReadOnlyArray)。遗憾的是,我们不得不处理我们的遗留问题、缺点和所有问题。
(fun str->box str)
=>
box
?@RamonSnir-是的,与向上转换相比,使用部分应用程序的能力是装箱的一个优势,尽管它当然只在转换为obj的情况下起作用。
让向上转换'列表。…map upcas-t'
被推断为
列表类型。
 | _ -> content |> split " "|> Array.map (fun s->s:>obj)//make sure obj[] is returned
let buildArgs content :obj[] = ... // Type mismatch
let values : obj[] = [|"a";"b";"c"|]