F# return byref 来自 CollectionsMarshal.GetValueRefOrAddDefault

F# return byref from CollectionsMarshal.GetValueRefOrAddDefault

我正在尝试获取从 CollectionMarshal.GetValueRefOrAddDefault 方法返回的 byref<int>。现在 tint 但我想要 byref<int>.

open System.Runtime.InteropServices
let d = System.Collections.Generic.Dictionary<int, int>()

let t, _ = CollectionsMarshal.GetValueRefOrAddDefault (d, 1)

F# 文档说要在方法调用前添加 &,但随后编译器 returns 出错。

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)

这里发生的事情是您正在尝试 de-sugar 编译器试图糖化的内容(隐式可变占位符参数),但在 IMO 中,编译器糖化事物的方式存在差距。你可以合理地论证 let struct(wasAdded, value) = CollectionsMarshal.GetValueRefOrAddDefault(d, 1) 可能是一个合理的脱糖,因为没有分配等等

无论如何,在您的示例中,让我们看看您尝试调用的成员的签名:

GetValueRefOrAddDefault : System.Collections.Generic.Dictionary<'Key, 'Value> * 'Key * byref<bool> -> byref<'Value>

编译器有一个方法模式,其参数列表以 out/byref 值和 return byref 值结尾:它将为您完成所有簿记工作。我的意思是它将为您初始化 let mutable x = Unchecked.defaultof<_> 单元格,使用这些单元格的 ref 值调用方法,并为您提供最终答案。

因为你想做快速的事情,你只需要自己包装而不是让编译器脱糖。