возвращение в F # 4.5 - PullRequest
       51

возвращение в F # 4.5

0 голосов
/ 26 июня 2018

Я пытаюсь добавить интерфейс типа F # к типу, который имеет метод возврата byref.Вот код:

type IPool<'P, 'T when 'T: struct> =
  abstract member GetReference: ITypedPointer<'P, 'T> -> byref<'T>

let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) pointer =
  pool.GetReference pointer

Теперь, к моему удивлению, похожая вещь работала нормально, пока я не представил IPool интерфейс.До этого сам Ref содержал реализацию, подобную &pool.data.[idx], и работал нормально.

Я пытался установить ночную сборку F # Tools, потому что последняя версия официально не поддерживает возврат byref, и PR для их представления был недавно завершен:https://github.com/Microsoft/visualfsharp/pull/4888

Тем не менее, я все еще получаю error FS3209: The address of the variable 'copyOfStruct' cannot be used at this point. A method or function may not return the address of this local value. в Visual Studio.Тип outref<T> все еще не доступен.Я что-то упустил?

Я также попытался удалить параметр pointer и просто вернуть pool.GetReference, чтобы получить только другое сообщение об ошибке.

Добавление: конечная цель - бытьспособен делать

let aref = Ref pool ptr
let bref = Ref pool ptr
aref <- 42
assert(aref = bref)

например, давать вызывающей стороне прямую ссылку на внутреннюю память, обычно поддерживаемую массивом, аналогично Span<T>.Я делаю это из соображений производительности, поэтому не стоит выделять при каждом вызове ссылку.

Ответы [ 2 ]

0 голосов
/ 24 июля 2018

По некоторым причинам уменьшение обобщения помогло избавиться от ошибки:

let Ref<'P, 'T when 'T: struct> (pool: IPool<'P, 'T>) pointer = pool.GetReference pointer

Решение, предоставленное

https://github.com/Microsoft/visualfsharp/issues/5366#issuecomment-407521220

Хотя это не объясняет, почемуоригинальный код не компилируется.

0 голосов
/ 26 июня 2018

Я не думаю, что стандартная практика - возвращать тип byref.Этот тип действительно предназначен для параметров метода, в основном для взаимодействия C # с параметрами out или ref.Посмотрите на этот вопрос StackOverflow для хорошего объяснения.

Что вы можете сделать, это изменить метод в вашем интерфейсе так, чтобы он принимал кортеж ITypedPointer<'P,'T> и byref<'T> (использование byref недопустимо для параметров с карри) и вместо него возвращал unit.Затем вы можете вызвать GetReference как любой стандартный метод .NET с параметром out в C #.Это будет выглядеть примерно так:

type ITypedPointer<'P, 'T> = interface end

type IPool<'P, 'T when 'T: struct> =
  abstract member GetReference: ITypedPointer<'P, 'T> * byref<'T> -> unit

let Ref<'TPool, 'P, 'T when 'TPool :> IPool<'P, 'T>> (pool: 'TPool) pointer =
  let mutable value = Unchecked.defaultof<'T>
  pool.GetReference(pointer, &value)
  value
...