2011-02-17 28 views
22

好吧,我開始明白F#能夠管理引用(某種類似C++的引用)。這使得可以改變函數中傳遞的參數的值,並且使程序員能夠返回多於一個值。 但是這是我需要知道:理解byref,ref和&

  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 
    

    雖然:=運營商只是讓我的編輯這樣的值:

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

    所以(Bang)取消引用我的參考。並:=編輯它。我想這也是正確的。

  3. & operator:這個操作符是做什麼的?它是否適用於參考類型?不,我猜它必須應用於可變值,並返回什麼?參考資料?地址?如果使用互動:所以我不明白&運營商是什麼

    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 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 
    
+8

風格提示:多個問號不會讓您的問題更加「質疑」,它們讓您看起來有點傻:一個就足夠了。全部大寫的文本很難閱讀,通常被理解爲意味着你在大喊:使用[格式化](http://stackoverflow.com/editing-help)(如斜體和粗體)來強調。 – 2011-02-17 11:37:20

回答

25

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是一種特殊類型,可以是隻用於方法參數(合理的)。這意味着參數本質上應該是指向某個內存位置的指針(分配在堆或堆棧上)。它對應於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從堆上分配基準單元格的值。

(可以使用使用refbyref參數,因爲編譯器專門處理這種情況下創造的價值 - 它會自動拍攝Value領域的引用,因爲這是一個有用的場景......)。

+0

非常感謝Tomas :) – Andry 2011-02-17 12:12:56