F# 4.5 中的 byref return
byref return in F# 4.5
我正在尝试向具有 byref return 方法的类型添加 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# 工具的夜间构建,因为最新版本不正式支持 byref returns,介绍它们的 PR 最近完成:https://github.com/Microsoft/visualfsharp/pull/4888
但是,我仍然在 Visual Studio 中得到 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.
。输入 outref<T>
似乎仍然不可用。我错过了什么吗?
我也尝试删除 pointer
参数,只是 return pool.GetReference
只得到不同的错误消息。
补充:最终目标是能够做到
let aref = Ref pool ptr
let bref = Ref pool ptr
aref <- 42
assert(aref = bref)
例如为调用者提供对内部存储器的直接引用,通常由数组支持,类似于 Span<T>
。我这样做是出于性能原因,所以在每次调用 Ref.
时都分配是不可行的
我认为 return byref
类型不是标准做法。这种类型实际上用于方法参数,主要用于与 out
或 ref
参数的 C# 互操作。看看 this Whosebug question 以获得很好的解释。
你可以做的是改变你界面上的方法来获取 ITypedPointer<'P,'T>
和 byref<'T>
的元组(柯里化参数不允许使用 byref
)和 return unit
代替。然后,您可以像在 C# 中使用 out
参数调用任何标准 .NET 方法一样调用 GetReference
。那看起来像这样:
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
出于某种原因,减少泛化有助于消除错误:
let Ref<'P, 'T when 'T: struct> (pool: IPool<'P, 'T>) pointer = pool.GetReference pointer
解决方案由
提供
https://github.com/Microsoft/visualfsharp/issues/5366#issuecomment-407521220
虽然没有解释原代码编译不通过的原因
我正在尝试向具有 byref return 方法的类型添加 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# 工具的夜间构建,因为最新版本不正式支持 byref returns,介绍它们的 PR 最近完成:https://github.com/Microsoft/visualfsharp/pull/4888
但是,我仍然在 Visual Studio 中得到 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.
。输入 outref<T>
似乎仍然不可用。我错过了什么吗?
我也尝试删除 pointer
参数,只是 return pool.GetReference
只得到不同的错误消息。
补充:最终目标是能够做到
let aref = Ref pool ptr
let bref = Ref pool ptr
aref <- 42
assert(aref = bref)
例如为调用者提供对内部存储器的直接引用,通常由数组支持,类似于 Span<T>
。我这样做是出于性能原因,所以在每次调用 Ref.
我认为 return byref
类型不是标准做法。这种类型实际上用于方法参数,主要用于与 out
或 ref
参数的 C# 互操作。看看 this Whosebug question 以获得很好的解释。
你可以做的是改变你界面上的方法来获取 ITypedPointer<'P,'T>
和 byref<'T>
的元组(柯里化参数不允许使用 byref
)和 return unit
代替。然后,您可以像在 C# 中使用 out
参数调用任何标准 .NET 方法一样调用 GetReference
。那看起来像这样:
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
出于某种原因,减少泛化有助于消除错误:
let Ref<'P, 'T when 'T: struct> (pool: IPool<'P, 'T>) pointer = pool.GetReference pointer
解决方案由
提供https://github.com/Microsoft/visualfsharp/issues/5366#issuecomment-407521220
虽然没有解释原代码编译不通过的原因