我正在使用Microsoft.FSharp.Reflection.FSharpValue.MakeUnion
,这需要Reflection.UnionCaseInfo
和obj[]
(可以为空)作为参数。
然而,我得到了一个
使用Type mismatch. Expecting a obj [] but given a string [] The type 'obj' does not match the type 'string'
函数的结果进行调用时string[]
。
我可以创建这个事件的最简单的例子如下(我有一个测试包围了它,因为标记为!!
的行,它没有编译。
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.
我不确定我是不是要将字符串[]转换/转换成obj []或者......好吧,如果我只是做了其他错误而我不知道的事情。
编辑:实际问题如下所述
let split (by:string) (input:string) = System.Text.RegularExpressions.Regex.Split(input,by)
let buildArgs content =
match content with
| "" -> [||]
| _ -> content |> split " " //Type mismatch
这就是我过去常常要解决的问题:有更好的方法吗?
| _ -> content |> split " "|> Array.map (fun s->s:>obj)//make sure obj[] is returned
Casting and Conversions (F#)作为参考
我也试过这个
let buildArgs content :obj[] = ... // Type mismatch
但这也给了我一个错误:
如果我不执行
Array.map
,请在功能的最后一行输入不匹配。
答案 0 :(得分:5)
我认为你目前的做法很好;有时我会发现类似[|for str in ... -> box str|]
的内容比... |> Array.map (fun str -> box str)
更具可读性,但您的里程可能会有所不同。至于你遇到这个问题的原因,这里有两个有些微妙的问题。
正如Phil Trelford的评论所暗示的那样,.NET类型系统允许将string[]
视为obj[]
(尽管从F#执行此操作需要向上转发和向下转换,即使.NET类型系统不是那么严格。在我看来,这种类型的系统"功能"这是令人厌恶的,我通常会避免它,即使在这种情况下它可能是安全的(对于阵列协方差的不可取性的同意见,见Covariance and Contravariance in C#, Part Two: Array Covariance和Array covariance: not just ugly, but slow too)。
因此,一般情况下,编译器不会将string[]
视为obj[]
。传递[|"a"; "b"; "c"|]
时为什么一切都很好?这里的答案是,在数组文字的特定情况下,编译器允许数组表达式的类型是每个元素的类型的超类型,如果可以推断出这样的超类型(例如因为它被约束为obj[]
通过另一种方法的签名,如您的情况)。但是,这仅适用于数组文字(即[|e1; e2; ... |]
形式的表达式)。
答案 1 :(得分:4)
如果定义一个变量来保留对象数组,那么你也可以使用类型注释,F#会自动将字符串向上转换为对象:
let values : obj[] = [|"a";"b";"c"|]
更一般地说,如果编译器在找到表达式之前知道目标类型(它从左到右看),那么即使文字包含字符串,它也会自动构建一个对象数组。您的问题也是函数调用的情况。
但是,创建string[]
类型的值后,您必须以某种方式将其转换为obj[]
(由其他人回答)。