开发者

Array covariance in F#

开发者 https://www.devze.com 2023-04-03 02:39 出处:网络
Since .NET arrays are covariant, the following works in C#: var strArray = new string[0]; object[] objArray = strAr开发者_如何学运维ray;

Since .NET arrays are covariant, the following works in C#:

var strArray = new string[0];
object[] objArray = strAr开发者_如何学运维ray;

In F#, given an array, 'T[], what would be the best way to convert it to obj[], without re-creating the array (e.g., Array.map box)? I'm using (box >> unbox), but it feels sloppy.


As Brian says, there's nothing wrong with box >> unbox, other that the fact that array covariance is inherently broken (e.g. ([| "test" |] |> box |> unbox<obj[]>).[0] <- obj() will throw an ArrayTypeMismatchException when trying to perform the assignment).

Instead, you would probably be better off treating a string[] as an obj seq, which is perfectly safe (although it still requires boxing and unboxing in F# since F# doesn't support generic co/contra-variance). Unfortunately, you do lose random access if you go this route.


box >> unbox

seems like a good idea; O(1), and does the job, apparently.

Consider also not using this CLR mis-feature. ;)


Brian's solution looks fine to me, but do you really need array covariance?

If you have a function that takes ISomething[] and want to pass it SomeSomething[] then you need it, but if the function only reads values of type ISomething from the array (which is what the covariance allows), then you could use hash-type and write a function that takes #ISomething[]. (Assuming that you can modify the function, of course!)

This way, the function can work on array of any elements that implement ISomething and you don't need array covariance when calling it. Here is an example:

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

It seems to me that the main reason for array covariance in .NET is that it was needed at the time when generics did not exist, but it seems that F# can live without this feature just fine.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号