为什么我不允许在let函数中使用引用单元格作为byref参数的参数?

时间:2013-01-25 17:10:10

标签: f#

这不起作用:

let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(xxx) // this expression was expected to have type
               // byref<int> but here has type int ref

但这有效:

let incrementParam(a: int byref) = a <- a + 1
let mutable b = 30
incrementParam(&b)

以及:

type Incrementor =
    static member Increment(i : int byref) =
       i <- i + 1

let fff = ref 10
Incrementor.Increment(fff) 

2 个答案:

答案 0 :(得分:6)

因为规范是这样说的。请参阅Type Directed Conversions at Member Invocations(强调我的),尤其是以下内容:

  

注意:这些类型定向转换主要用于与现有基于成员的.NET库的互操作性,不适用于模块中定义的函数的调用或表达式中本地绑定的函数。

答案 1 :(得分:5)

要向Daniel指出的引用添加一些细节,问题是类型'T ref与类型'T byref不同,因此编译器需要插入一些转换(以便地址)。

我认为只支持成员,因为这是主要场景(调用COM互操作方法等),因为隐式转换通常会编译类型推断。类型定向转换是一种更容易的情况,编译器已经知道所需的类型('T byref)。我想,如果在函数上允许这样做,编译器可能会推断出参数的类型实际上应该是'T ref

如果您想让第一个样本生效,您必须通过获取'T byref字段的地址来显式构建contents

let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(&xxx.contents)