Ковариация массива в F # - PullRequest
       19

Ковариация массива в F #

5 голосов
/ 07 сентября 2011

Поскольку массивы .NET являются ковариантными, в C # работает следующее:

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

В F # для массива 'T[], что будет лучшим способом преобразовать его в obj[],без повторного создания массива (например, Array.map box)?Я использую (box >> unbox), но он кажется неаккуратным.

Ответы [ 3 ]

5 голосов
/ 07 сентября 2011

Как говорит Брайан, в box >> unbox нет ничего плохого, кроме того факта, что ковариация массива по своей сути нарушена (например, ([| "test" |] |> box |> unbox<obj[]>).[0] <- obj() вызовет исключение ArrayTypeMismatchException при попытке выполнить назначение).

Вместо этого вам, вероятно, было бы лучше трактовать string[] как obj seq, что совершенно безопасно (хотя в F # он все еще требует упаковки и распаковки, так как F # не поддерживает универсальную co / contra-дисперсию). К сожалению, вы теряете произвольный доступ, если идете по этому маршруту.

4 голосов
/ 07 сентября 2011
box >> unbox

кажется хорошей идеей;O (1), и делает работу, по-видимому.

Также рассмотрите возможность использования этой ошибки CLR.;)

3 голосов
/ 07 сентября 2011

Решение Брайана мне подходит, но вам действительно нужна ковариация массива?

Если у вас есть функция, которая принимает ISomething[] и хотите передать ее SomeSomething[], тогда вам это нужно, но если функция читает только значения типа ISomething из массива (что позволяет ковариация), тогда вы можете использовать хеш-тип и написать функцию, которая принимает #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 # вполне может без этой функции жить.

...