嗯,我开始明白 F# 能够管理引用(某种类似于 C++ 的引用)。这使更改函数中传递的参数值成为可能,并使程序员能够返回多个值。
但是,这是我需要知道的:
ref
用于从值创建对推断类型的该值的引用。所以let myref = ref 10
这意味着 F# 将创建一个类型为
Ref<int>
的对象。放在那里(在可变字段中)我的 int 10
.好的。所以我假设
ref
用于创建 Ref<'a>
的实例类型。这是正确的吗? let myref = ref 10
let myval = myref.Value
let myval2 = !myref
而
:=
运算符只是让我像这样编辑值:let myref = ref 10
myref.Value <- 30
myref := 40
所以
!
(Bang) 取消引用我的引用。和 :=
编辑它。我想这也是正确的。 let mutable mutvar = 10;;
&a;;
最后一行抛出了一个错误,所以我不明白
&
是什么意思运营商是为了。 byref
?这对我来说非常重要,但我意识到我不理解它。我知道它用于有关参数传递的功能。当他希望可以编辑传递的值时使用 byref (这有点违反函数式语言的哲学,但 f# 不止于此)。考虑以下:
let myfunc (x: int byref) =
x <- x + 10
这很奇怪。我知道如果你有引用
let myref = ref 10
然后执行此操作以编辑值:myref <- 10
它出现错误,因为它应该是这样的:myref := 10
.然而,事实上我可以在该函数中编辑 x
使用 <-
运算符意味着 x
不是引用吧?如果我假设
x
不是引用,那么我还假设,在函数中,当使用 byref
时在参数上,该参数可以应用可变语法。所以这只是一个语法问题,如果我假设我没问题,事实上,一切正常(没有编译器错误)。然而,什么是x
? &
运算符(operator)参与但你能解释一下吗?在本文中:MSDN Parameters and Arguments提供了以下示例:type Incrementor(z) =
member this.Increment(i : int byref) =
i <- i + z
let incrementor = new Incrementor(1)
let mutable x = 10
// A: Not recommended: Does not actually increment the variable. (Me: why?)
incrementor.Increment(ref x)
// Prints 10.
printfn "%d" x
let mutable y = 10
incrementor.Increment(&y) (* Me: & what does it return? *)
// Prints 11.
printfn "%d" y
let refInt = ref 10
incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *)
// Prints 11.
printfn "%d" !refInt
最佳答案
引用关键字 是的,当你写 let a = ref 10
您实际上是在写 let a = new Ref<int>(10)
哪里Ref<T>
type 有一个可变字段 Value
.
访问值 :=
和 !
运算符只是编写的快捷方式:
a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
ByRef 是一种特殊类型,可以(合理地)仅在方法参数中使用。这意味着参数本质上应该是指向某个内存位置(分配在堆或堆栈上)的指针。对应于
out
和 ref
C#中的修饰符。请注意,您不能创建这种类型的局部变量。& 运算符 是一种创建值(指针)的方法,该值可以作为参数传递给期望
byref
的函数/方法。类型。调用函数
byref
的例子之所以有效,是因为您正在向该方法传递对局部可变变量的引用。通过引用,该方法可以更改存储在该变量中的值。以下不起作用:
let a = 10 // Note: You don't even need 'mutable' here
bar.Increment(ref a)
原因是您正在创建
Ref<int>
的新实例。并且您正在复制 a
的值进入这个实例。 Increment
方法然后修改存储在 Ref<int>
实例中的堆上的值,但您不再拥有对该对象的引用。let a = ref 10
bar.Increment(a)
这是有效的,因为
a
是类型 Ref<int>
的值并且您将指向堆分配实例的指针传递给 Increment
然后使用 !a
从堆分配的引用单元格中获取值.(您可以使用使用
ref
创建的值作为 byref
的参数,因为编译器专门处理这种情况 - 它会自动引用 Value
字段,因为这是一个有用的场景......)。
关于.net - 理解byref、ref和&,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5028377/