好吧,我开始明白F#能够管理引用(某种类似于引用的C++)。这使得可以更改函数中传递的参数的值,也使程序员能够返回多个值。然而,这是我需要知道的:

  1. Ref关键字:关键字 ref 用于根据值创建对推断类型的该值的引用。所以

    let myref = ref 10
    

    这意味着F#将创建一个类型的对象 Ref<int> 把那里(在可变的领域)我的 int 10.

    好的。所以我想 ref 用于创建 Ref<'a> 类型。这是正确的吗?

  2. 访问值:为了访问存储在引用中的值,我可以这样做:

    let myref = ref 10
    let myval = myref.Value
    let myval2 = !myref
    

    := operator只是让我这样编辑值:

    let myref = ref 10
    myref.Value <- 30
    myref := 40
    

    所以 ! (砰)取消引用我的参考。和 := 编辑它。我想这也是正确的。

  3. 运营商:这个操作员是做什么的?是否要应用于引用类型?不,我想它必须应用于可变值,这返回什么?参考书?地址?如果使用交互式:

    let mutable mutvar = 10;;
    &a;;
    

    最后一行抛出一个错误,所以我不明白 & 运营商是为。

  4. 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?

  5. 调用函数:如何使用利用byref参数的函数?

    & 接线员也参与其中,但你能更好地解释一下吗?在本文中: MSDN参数和参数 提供了以下示例:

    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
    
有帮助吗?

解决方案

Ref关键字 是的,当你写 let a = ref 10 你基本上是在写作 let a = new Ref<int>(10) 在哪里 Ref<T> 类型具有可变字段 Value.

访问值:=! 运算符只是写作的捷径:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

ByRef 是一种特殊类型,可以(合理地)仅在方法参数中使用。这意味着参数本质上应该是指向某些内存位置(在堆或堆栈上分配)的指针。它对应于 outref 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 字段,因为这是一个有用的场景。..).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top