Я пытаюсь получить byref<int>
, возвращаемый методом CollectionMarshal.GetValueRefOrAddDefault
. Сейчас t
это int
, но я хочу byref<int>
.
open System.Runtime.InteropServices
let d = System.Collections.Generic.Dictionary<int, int>()
let t, _ = CollectionsMarshal.GetValueRefOrAddDefault (d, 1)
В документах F# говорится, что перед вызовом метода нужно добавлять &
, но тогда компилятор возвращает ошибку.
let t, _ = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1)
// Error:
// Cannot take the address of the value returned from the expression.
// Assign the returned value to a let-bound value before taking the address.
// F# Compiler3236
Вот пример кода для иллюстрации решения:
open System.Runtime.InteropServices
// without this you get a warning about the byref-typed `v` being a top-level value in a module
type Blah() =
let d = System.Collections.Generic.Dictionary<int, int>()
let mutable t = Unchecked.defaultof<_>
let v = &CollectionsMarshal.GetValueRefOrAddDefault (d, 1, &t)
Здесь происходит то, что вы пытаетесь обезжирить то, что компилятор пытается обсахарить (неявные изменяемые параметры-заполнители), но здесь есть пробел, IMO, в том, как компилятор подсахаривает вещи. Вы могли бы привести разумный аргумент, что let struct(wasAdded, value) = CollectionsMarshal.GetValueRefOrAddDefault(d, 1)
может быть разумным обескураживанием из-за отсутствия распределений и т. д. и т. д.
Во всяком случае, в вашем примере давайте посмотрим на подпись члена, которого вы пытаетесь вызвать:
GetValueRefOrAddDefault : System.Collections.Generic.Dictionary<'Key, 'Value> * 'Key * byref<bool> -> byref<'Value>
У компилятора есть шаблон для методов, имеющих списки параметров, которые заканчиваются значениями out/byref и возвращают значения byref: он сделает всю бухгалтерию за вас. Под этим я подразумеваю, что он инициализирует для вас ячейки let mutable x = Unchecked.defaultof<_>
, вызовет метод со значениями ref для этих ячеек и даст вам окончательные ответы.
Поскольку вы хотите делать что-то быстро, вам просто нужно сделать эту упаковку самостоятельно, вместо того, чтобы позволить компилятору избавиться от сахара.