本文介绍了obj []和string []作为参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



类型不匹配。期望一个obj []但给定一个字符串[]类型'obj'不匹配类型'string'当调用的函数的结果是 string [ ]



我可以创建的最简单的例子如下(我有一个测试包裹在这里,它不编译,因为标记 !!

  let one(a:obj [])= a |> Array.map(fun o-> printfn%Ao)|> ignore 
one [|a;b;c|] // OK!
let str = [|a;b;c|] //相当于我的函数return
one str // !!类型不匹配
pre>

我不知道我是否正在将字符串[]转换为obj []或转换为...好吧,如果我只是做别的事


$ b

$ b

  let split(by:string)(input:string)= System.Text.RegularExpressions.Regex.Split(input,by)

let buildArgs content =
匹配内容与
| - > [||]
| _ - > content |> split//类型不匹配



这是我用来解决的:有更好的方法吗?

  | _  - >内容|> split|> Array.map(fun s-> s:> obj)//确保返回obj [] 

作为参考



我也尝试过这个



  let buildArgs :obj [] = ... //类型不匹配

但也会给我一个错误: / p>


解决方案

有时我会找到像 [| str in ... - > box str |] ... |> Array.map(fun str - > box str)但您的里程可能会有所不同。至于为什么你碰到这个,这里有两个微妙的问题。



正如Phil Trelford的评论暗示,.NET类型系统允许将 string [] 视为 obj [] (虽然这样做从F#需要一个向上和向下转换,即使.NET类型系统不是这么严格)。在我看来,这种类型的系统功能是可憎的,我通常会避免它,即使它可能是安全的在这种情况下(对于不合意的数组协方差的意见,见和



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


I am using Microsoft.FSharp.Reflection.FSharpValue.MakeUnion and this requires a Reflection.UnionCaseInfo and an obj[] (that can be empty) as parameters.

However, I am getting aType mismatch. Expecting a obj [] but given a string [] The type 'obj' does not match the type 'string' when calling with the result of a function that is a string[].

The simplest example I can create of this happening is as follows (I have a test wrapped around this and it doesn't compile because of the line marked !!.

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.

I am not sure if I am meant to be casting/converting string[] into an obj[] or ... well, if I am just doing something else wrong that I don't know about.

edit: the actual issue is as described below

let split (by:string) (input:string) = System.Text.RegularExpressions.Regex.Split(input,by)

let buildArgs content =
 match content with
 | "" -> [||]
 | _ -> content |> split " " //Type mismatch

this is what I used to solve: is there a better way?

 | _ -> content |> split " "|> Array.map (fun s->s:>obj)//make sure obj[] is returned

Casting and Conversions (F#) as reference

I have also tried this

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

but that also gives me an error:

解决方案

I think your current approach is fine; sometimes I find something like [|for str in ... -> box str|] to be a bit more readable than ... |> Array.map (fun str -> box str) but your mileage may vary. As to why you run into this, there are two somewhat subtle issues here.

As Phil Trelford's comments imply, the .NET type system allows string[] to be treated as obj[] (though doing this from F# requires an upcast and downcast even though the .NET type system isn't so strict). In my opinion this type system "feature" is an abomination and I'd generally avoid it even though it's probably safe in this case (for concurring opinions on the undesirability of array covariance see Covariance and Contravariance in C#, Part Two: Array Covariance and Array covariance: not just ugly, but slow too).

So in general, a string[] won't be treated as an obj[] by the compiler. Why then is everything fine when you pass in [|"a"; "b"; "c"|]? The answer here is that in the specific case of array literals the compiler allows the type of an array expression to be a supertype of each element's type if such a supertype can be inferred (e.g. because it's constrained to obj[] by the signature of another method, as in your case). However, this only works in the case of array literals (that is, expressions of the form [|e1; e2; ... |]).

这篇关于obj []和string []作为参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 22:56