将F#中的对象传递给C#方法并将其作为out参数不起作用?

Tim*_*hyP 3 c# f# pass-by-reference

我正在使用的其中一个库在C#中定义了这个:

public ushort GetParameterSet(string name, out ParameterSet parameterSet)
Run Code Online (Sandbox Code Playgroud)

我试图用F#调用它:

let parameterSet = new ParameterSet();
let retVal = currentPanel.GetParameterSet(name, ref parameterSet);
Run Code Online (Sandbox Code Playgroud)

但是,即使在C#方法中将parameterSet设置为具有有效数据的该类的实例,它也不会在F#中更改.

我在这里错过了什么?

Pav*_*aev 11

首先,为什么你的代码不能正常工作:ref在F#中的含义与在C#中的含义不同.在F#中,'a ref是一种类型.这也不是神奇的 - 它只是一个单一字段的记录contents,定义如下:

type 'a ref = { mutable contents : 'a }
Run Code Online (Sandbox Code Playgroud)

不是指向局部变量的指针或引用.因此,当你写这个:

let x = 0
let y = ref x
Run Code Online (Sandbox Code Playgroud)

没有变量y引用x.相反,您有y类型的变量int ref,其值已contents初始化为具有的值x(即0).你可以改变:

y.contents <- 1
Run Code Online (Sandbox Code Playgroud)

这不会改变它的价值x.它只会改变它的价值contents

F#还提供了一些语法糖'a ref.具体来说,这个:

y.contents <- y.contents + 1
Run Code Online (Sandbox Code Playgroud)

可写得更短:

y := !y + 1
Run Code Online (Sandbox Code Playgroud)

因此:=是用于分配给一个速记contents,并且!是用于读取其值的简写.

有关详细信息,请参阅MSDN中的参考单元格ref.

现在,F#有关联的魔法施放'a ref类型,让你通过该类型的实例,以期望一个外国函数byref的参数(包括refout在C#地图byref中IL).在这种情况下,如果函数改变参数的值,价值contents在你的ref情况下相应地改变.在您的示例中,ref parameterSet创建了一个新实例ref,将其传递给更改它的函数,然后将其丢弃.你应该做的是:

let parameterSet = ref(new ParameterSet())
let retVal = currentPanel.GetParameterSet(name, parameterSet)
...
// use parameterSet.contents as needed
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用let mutable声明一个可变局部变量,然后使用魔法&运算符将其直接传递给函数byref:

let mutable parameterSet = new ParameterSet()
let retVal = currentPanel.GetParameterSet(name, &parameterSet)
Run Code Online (Sandbox Code Playgroud)