好吧,我开始了解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)取消引用了我的引用。然后:=对其进行编辑。我想这也是正确的。
  • &运算符:该运算符做什么?是否将其应用于引用类型?不,我想必须将其应用于可变值,这会返回什么?引用资料?地址?如果使用交互式:
    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
    
  • 最佳答案

    引用关键字是的,当您编写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 是一种特殊类型,只能(合理地)仅在方法参数中使用。这意味着该参数本质上应该是指向某个内存位置(分配在堆或堆栈上)的指针。它对应于C#中的outref修饰符。请注意,您不能创建这种类型的局部变量。

    &运算符是一种创建值(指针)的方法,该值可以作为参数传递给需要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)
    

    这是可行的,因为aRef<int>类型的值,并且您将指向堆分配的实例的指针传递给Increment,然后使用!a从堆分配的引用单元中获取值。

    (您可以将使用ref创建的值用作byref的参数,因为编译器专门处理这种情况-因为这是一个有用的场景,它将自动引用Value字段...)。

    09-05 20:02