简体   繁体   中英

Array covariance in F#

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

var strArray = new string[0];
object[] objArray = strArray;

In F#, given an array, 'T[] , what would be the best way to convert it to obj[] , without re-creating the array (eg, 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 (eg ([| "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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM