一般情况下,F#函数可以通过调用new DelegateType
转换为委托(delegate)。并将函数作为参数传入。但是当委托(delegate)包含 byref
参数,这是不可能的。例如代码:
type ActionByRef<'a> = delegate of 'a byref -> unit
let f (x:double byref) =
x <- 6.0
let x = ref 42.0
let d = new ActionByRef<_>(f)
无法编译,出现以下错误:
This function value is being used to construct a delegate type whose signature includes a byref argument. You must use an explicit lambda expression taking 1 arguments.
出现错误后,修改代码以使用
let d = new ActionByRef<_>(fun x -> f(&x))
作品。但我的问题是:为什么这是必要的?为什么 F# 不允许从命名函数转换到此委托(delegate),但从 lambda 转换很好?
我在研究 another question 时发现了这种行为.我意识到
byref
仅用于与其他 .Net 语言兼容。
最佳答案
我认为问题在于 byref<'T>
不是 F# 中的实际类型 - 它看起来像一个类型(使语言更简单),但它被编译为标有 out
的参数旗帜。这意味着 byref<'T>
只能在编译器实际可以使用 out
的地方使用旗帜。
函数值的问题在于您可以构造函数,例如通过部分应用:
let foo (n:int) (b:byref<int>) =
b <- n
当你通过
foo
作为委托(delegate)构造函数的参数,它是部分应用程序(没有参数)的特定情况,但部分应用程序实际上需要构造一个新方法,然后将其交给委托(delegate):type IntRefAction = delegate of byref<int> -> unit
let ac = IntRefAction(foo 5)
编译器可以很聪明,并使用
byref
生成新方法参数(或 out
标志),然后通过引用将其传递给实际函数,但通常,当您不使用 fun ... -> ...
时,还会有其他编译器生成的方法句法。处理这会增加复杂性,我认为这是一个相对罕见的情况,所以 F# 编译器不会这样做,并要求你更明确......
关于f# - 为什么不能将带有 byref 的函数直接转换为委托(delegate)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9078689/