6

我正在使用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.

我不确定我是否打算将 string[] 转换/转换为 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

铸造和转换 (F#)作为参考

我也试过这个

let buildArgs content :obj[] = ... // Type mismatch

但这也给了我一个错误:

如果我不执行Array.map.

4

2 回答 2

5

我认为您目前的方法很好;有时我发现一些东西[|for str in ... -> box str|]比它更具可读性,... |> Array.map (fun str -> box str)但你的里程可能会有所不同。至于你为什么会遇到这个问题,这里有两个有点微妙的问题。

正如 Phil Trelford 的评论所暗示的,.NET 类型系统允许string[]被视为obj[](尽管从 F# 执行此操作需要向上转换和向下转换,即使 .NET 类型系统并不那么严格)。在我看来,这种类型系统的“特性”是可憎的,我通常会避免它,即使在这种情况下它可能是安全的(对于不受欢迎的数组协方差的一致意见,请参阅C# 中的协方差和逆变,第二部分:数组协方差数组协方差:不仅丑陋,而且也很慢)。

所以一般来说, a不会被编译器string[]视为 a 。obj[]那为什么当你通过时一切都很好[|"a"; "b"; "c"|]?这里的答案是,在数组文字的特定情况下,如果可以推断出这样的超类型,编译器允许数组表达式的类型成为每个元素类型的超类型(例如,因为它受obj[]另一个方法的签名约束,如在你的情况下)。但是,这只适用于数组字面量(即形式的表达式[|e1; e2; ... |])。

于 2013-08-18T20:14:36.090 回答
4

如果你定义一个变量来保存对象数组,那么你也可以使用类型注释,F# 会自动将字符串向上转换为对象:

let values : obj[] = [|"a";"b";"c"|]

更一般地说,如果编译器在找到表达式之前就知道目标类型(它从左到右查找),那么它会自动构建一个对象数组,即使字面量包含字符串。这也是您问题中的函数调用的情况。

但是,一旦您创建了 type 的值string[],您必须以obj[]某种方式将其转换为(正如其他人所回答的那样)。

于 2013-08-18T17:17:15.053 回答