由于.NET数组是协变的,因此以下适用于C#:
var strArray = new string[0];
object[] objArray = strArray;
在F#中,给定一个数组'T[]
,将其转换为obj[]
的最佳方式是什么,而无需重新创建数组(例如Array.map box
)?我正在使用(box >> unbox)
,但感觉很草率。
答案 0 :(得分:5)
正如Brian所说,box >> unbox
没有任何问题,除此之外,数组协方差本身就被破坏了(例如([| "test" |] |> box |> unbox<obj[]>).[0] <- obj()
会在尝试执行赋值时抛出ArrayTypeMismatchException。)
相反,您可能最好将string[]
视为obj seq
,这是非常安全的(尽管它仍然需要F#中的装箱和拆箱,因为F#不支持通用协同-方差)。不幸的是,如果你走这条路,你会失去随机访问。
答案 1 :(得分:4)
box >> unbox
似乎是一个好主意; O(1),并且显然完成了工作。
还要考虑不使用此CLR错误功能。 ;)
答案 2 :(得分:3)
Brian的解决方案对我来说很好,但你真的需要数组协方差吗?
如果你的函数需要ISomething[]
并想要传递它SomeSomething[]
那么你需要它,但是如果函数只从数组中读取类型ISomething
的值(这是协方差允许的是什么),然后你可以使用hash-type并编写一个带#ISomething[]
的函数。 (当然,假设你可以修改这个功能!)
这样,该函数可以处理实现ISomething
的任何元素的数组,并且在调用它时不需要数组协方差。这是一个例子:
type A() =
interface IDisposable with
member x.Dispose() = printfn "gone"
// Disposes the first element from an array
let disposeFirst (a:#IDisposable[]) = a.[0].Dispose()
// Call 'disposeFirst' with 'A[]' as an argument
let aa = [| new A(); new A() |]
disposeFirst aa
在我看来,.NET中数组协方差的主要原因是当泛型不存在时需要它,但似乎F#可以没有这个功能就好了。