3

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

public ushort GetParameterSet(string name, out ParameterSet parameterSet)

我试图从 F# 调用它:

let parameterSet = new ParameterSet();
let retVal = currentPanel.GetParameterSet(name, ref parameterSet);

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

我在这里想念什么?

4

2 回答 2

12

首先,为什么您的代码不能按原样运行:ref在 F# 中的含义与在 C# 中的含义不同。在 F# 中,'a ref是一个类型。它也不是神奇的——它实际上只是一个包含单个字段的记录contents,定义如下:

type 'a ref = { mutable contents : 'a }

不是对局部变量的指针或引用。因此,当您编写此代码时:

let x = 0
let y = ref x

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

y.contents <- 1

这不会改变 的值x。它只会改变contents

F# 还为'a ref. 具体来说,这个:

y.contents <- y.contents + 1

可以更短的写成:

y := !y + 1

因此:=是分配给的简写contents,并且!是读取其值的简写。

有关. _ _ref

现在 F# 有一个与'a ref类型关联的魔法转换,它允许您将该类型的实例传递给需要byref参数的外部函数(在 C# 中ref和在 IL中都out映射到)。byref在这种情况下,如果函数更改了参数的值,则实例contents中的值ref也会相应更改。在您的示例中,ref parameterSet创建了 的新实例ref,将其传递给更改它的函数,然后将其丢弃。你应该做的是:

let parameterSet = ref(new ParameterSet())
let retVal = currentPanel.GetParameterSet(name, parameterSet)
...
// use parameterSet.contents as needed

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

let mutable parameterSet = new ParameterSet()
let retVal = currentPanel.GetParameterSet(name, &parameterSet)
于 2009-08-13T19:33:55.093 回答
4

尝试

// let parameterSet = null;
let retval, parameterSet = currentPanel.GetParamterSet(name);

ref当方法需要一个 out 参数(调用时应该是out关键字前面的未分配引用)时,您不应该将实例作为参数传递。

于 2009-08-13T19:11:03.323 回答