Возврат byref в F # 4.5

Я пытаюсь добавить интерфейс стиля F # к типу, который имеет тип IPool < ' P , ' T, когда ' T : struct > = абстрактный член GetReference : ITypedPointer < ' P , ' T > -> byref < ' T > let Ref < ' TPool , ' P , ' T, когда ' TPool :> IPool < ' P , ' T >> ( пул : ' TPool ) pointer = pool . Метод возврата указателя GetReference . Вот код:

IPool

Теперь, к моему удивлению, подобная вещь отлично работала, пока я не представил &pool.data.[idx]интерфейс. Перед этой ошибкой FS3209: адрес переменной 'copyOfStruct' не может быть использован в этой точке. Метод или функция не может вернуть адрес этого локального значения. сама содержала реализацию, подобную outref<T>, и работала нормально.

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

Тем не менее, я все еще попадаю pool.GetReferenceв Visual Studio. Тип по- прежнему не доступен. Я что-то упускаю?let aref = Ref pool ptr let bref = Ref pool ptr aref <- 42 assert(aref = bref)

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

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

out

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

f#,byref,return-by-reference,

9

Ответов: 2


1

Я не думаю, что стандартная практика возвращает byrefтип. Этот тип действительно предназначен для параметров метода, в основном для взаимодействия с C # ITypedPointer<'P,'T>или refпараметров. Взгляните на этот вопрос StackOverflow для хорошего объяснения.

То, что вы можете сделать, это изменить метод на вашем интерфейсе, чтобы взять кортеж byref<'T>и byref(использование 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

1 принят

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

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

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

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

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

F #, ByRef, вернуться по ссылке,
Похожие вопросы