F# 4.5中的ByRef返回

9

我正在尝试为一个具有byref返回方法的类型添加F#风格的接口。 以下是代码:

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

但是,在Visual Studio中仍然会收到错误消息错误 FS3209:此时无法使用变量'copyOfStruct'的地址。方法或函数可能无法返回此局部值的地址。。类型outref<T>也似乎仍然不可用。我有什么遗漏吗?

我还尝试省略pointer参数,只返回pool.GetReference,结果得到另一条错误消息。

附加说明:最终目标是能够执行以下操作:

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

例如,为调用者提供一个内部存储器的直接引用,通常由数组支持,类似于Span<T>。出于性能原因,我正在制作这个功能,因此每次调用Ref时分配内存是不可行的。

2个回答

2

-1

我认为返回一个byref类型并不是标准做法。这种类型实际上是为方法参数而设计的,主要用于C#与outref参数的交互。可以查看这个StackOverflow问题以获得很好的解释。

你可以将接口上的方法更改为接受ITypedPointer<'P,'T>byref<'T>元组(不能在柯里化参数中使用byref),并返回unit。然后,你就可以像在C#中调用任何标准的.NET方法一样调用GetReference,带有一个out参数。代码如下:

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

2
整个想法是返回byref,以便方法用户可以执行以下操作:let x = Ref pool ptr; x <- 10 - LOST
2
你实际上可以在此文件的底部找到示例:https://github.com/lostmsu/ShortPointers/blob/5c700ee4bf7c79722c6448f9436b5ba4027c44ea/src/StructPool.fs - LOST
如果您只是想从另一个位置进行突变,为什么不使用标准的F# ref引用单元呢? - Aaron M. Eshbach
因为我需要客户端能够获取对数组元素的引用。let x = [| 1 |]; let r1 = ref x.[0]; let r2 = ref x.[0]; r1 := 2; !r2将产生1。如果我改用&x.[0],结果将是2 - LOST

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接