obj []和string []作为参数

时间:2013-08-18 16:57:10

标签: types casting f# type-conversion

我正在使用Microsoft.FSharp.Reflection.FSharpValue.MakeUnion,这需要Reflection.UnionCaseInfoobj[](可以为空)作为参数。

然而,我得到了一个 使用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,请在功能的最后一行输入不匹配。

2 个答案:

答案 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 CovarianceArray 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[](由其他人回答)。