好吧,我开始明白F#能够管理引用(某些类似C ++的引用)。这使得有可能改变函数中传递的参数值,并使程序员能够返回多个值。 然而,这是我需要知道的:
Ref关键字:关键字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)取消引用我的参考。 :=
编辑它。我想这也是正确的。
&amp; operator:这个运营商做什么?它是否适用于参考类型?不,我想它必须应用于一个可变值,这会返回什么?参考资料?地址?如果使用互动:
let mutable mutvar = 10;;
&a;;
最后一行引发错误,因此我不明白&
运算符的用途。
ByRef:byref
怎么样?这对我来说非常重要,但我意识到我不理解它。
我知道它用于参数传递的功能。当他想要传递的值可以被编辑时,人们会使用byref(这有点违背了函数式语言的哲学,但f#不仅仅是这个)。请考虑以下事项:
let myfunc (x: int byref) =
x <- x + 10
这很奇怪。我知道如果你有一个引用let myref = ref 10
,然后执行此操作来编辑值myref <- 10
,则会出现错误,因为它应该是这样的:myref := 10
。但是,在该功能中,我可以使用x
运算符编辑<-
,这意味着x
不是参考,对吗?
如果我假设x
不是引用,那么我还假设,在函数中,当对参数使用byref
时,该参数可以应用可变语法。所以这只是一个语法问题,如果我假设我没事,事实上,一切正常(没有编译器错误)。但是,x
是什么?
调用函数:如何使用函数使用byref参数?
&
运营商参与了,但您能否更好地解释一下?在本文中: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
答案 0 :(得分:28)
参考关键字是的,当您撰写let a = ref 10
时,您实际上是在let a = new Ref<int>(10)
类型具有可变字段Ref<T>
的{{1}}。
访问价值 Value
和:=
运算符只是写作的快捷方式:
!
ByRef 是一种特殊类型,可以(合理地)仅在方法参数中使用。这意味着参数本质上应该是指向某个内存位置的指针(在堆或堆栈上分配)。它对应于C#中的a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
和out
修饰符。请注意,您无法创建此类型的本地变量。
&amp; operator 是一种创建值(指针)的方法,该值可以作为参数传递给期望ref
类型的函数/方法。
调用函数 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
字段,因为这是一个有用的场景...)。