Udostępnij za pośrednictwem


Odwoływanie się do komórek (F#)

Odwołuje się do komórek są lokalizacji przechowywania, które umożliwiają utworzenie tych wartości z semantyką odniesienia.

ref expression

Uwagi

Za pomocą ref operatora przed wartość, aby utworzyć nowe komórki odniesienia, która hermetyzuje wartość.Następnie można zmienić wartości podstawowej, ponieważ mutable.

Komórka odniesienia przechowuje wartość rzeczywistą; nie jest tylko adres.Podczas tworzenia komórki odwołanie za pomocą ref operatora, utworzyć kopię jako encapsulated wartości dla tych wartości podstawowej.

Cofnięcia odwołania komórek odniesienia przy użyciu ! (wykrzyknika).

Poniższy przykład kodu ilustruje deklarację i użyj odwołania komórek.

// Declare a reference.
let refVar = ref 6

// Change the value referred to by the reference.
refVar := 50

// Dereference by using the ! operator.
printfn "%d" !refVar

Dane wyjściowe są 50.

Odwoływanie się do komórek są instancjami Ref typ rodzajowy rekordu, która jest zadeklarowana w następujący sposób.

type Ref<'a> =
    { mutable contents: 'a }

Typ 'a ref jest synonimem dla Ref<'a>.Kompilator i technologii IntelliSense w IDE wyświetlają Byłej dla tego typu, ale ten ostatni jest definicja podstawowych.

ref Operator tworzy nowe komórki odwołanie.Poniższy kod jest deklaracja z ref operatora.

let ref x = { contents = x }

W poniższej tabeli przedstawiono funkcje, które są dostępne w komórce odniesienia.

Operator, członka lub pola

Opis

Typ

Definicja

!(operator nieprawidłowego)

Zwraca wartości podstawowej.

'a ref -> 'a

let (!) r = r.contents

:=(operator przypisania)

Zmiany wartości podstawowej.

'a ref -> 'a -> unit

let (:=) r x = r.contents <- x

ref(operator)

Hermetyzuje wartość do nowej komórki odwołanie.

'a -> 'a ref

let ref x = { contents = x }

Value(właściwość)

Zwraca lub ustawia wartość podstawowej.

unit -> 'a

member x.Value = x.contents

contents(pola rekordu)

Zwraca lub ustawia wartość podstawowej.

'a

let ref x = { contents = x }

Do uzyskania dostępu do podstawowych wartości na kilka sposobów.Wartość zwracana przez dereference operator (!) nie jest możliwa do przypisania wartości.W związku z tym, w przypadku modyfikowania wartości podstawowej, należy użyć operatora przypisania (:=) zamiast.

Obie Value właściwości i contents pole to można przypisać wartości.W związku z tym można te dostępu albo zmienić wartości podstawowej, jak pokazano w poniższym kodzie.

let xRef : int ref = ref 10

printfn "%d" (xRef.Value)
printfn "%d" (xRef.contents)

xRef.Value <- 11
printfn "%d" (xRef.Value)
xRef.contents <- 12
printfn "%d" (xRef.contents)

Wprowadza dane wyjściowe.

10
10
11
12

Pole contents zapewnia zgodnooć z innymi wersjami ML i wygeneruje ostrzeżenie podczas kompilacji.Aby wyłączyć ostrzeżenia, należy użyć --mlcompatibility opcję kompilatora.Aby uzyskać więcej informacji, zobacz Opcje kompilatora (F#).

Przykład

Poniższy kod ilustruje wykorzystanie Ogniwa wzorcowe w parametrze, przekazując.Incrementor Typu ma metodę Increment pobierająca parametr, który zawiera byref w polu Typ parametru.byref w parametrze typu wskazuje, że wywołujący musi minąć komórki odwołanie lub adres typowe zmienną określonego typu, w tym przypadku int.Pozostały kod ilustruje sposób wywołania Increment z obu tych typów argumentów i przedstawia zastosowanie ref operatora na zmienną do utworzenia komórki odniesienia (ref myDelta1).Następnie prezentuje ono sposób użycia operatora z adresu (&) do generowania odpowiednich argument.Wreszcie Increment wywoływana jest metoda ponownie za pomocą komórki odniesienia, która jest zadeklarowana za pomocą let powiązania.Ostatnia linia kodu ilustruje użycie ! operatora do cofnięcia odwołania do komórki odwołanie do drukowania.

type Incrementor(delta) =
    member this.Increment(i : int byref) =
        i <- i + delta

let incrementor = new Incrementor(1)
let mutable myDelta1 = 10
incrementor.Increment(ref myDelta1)
// Prints 10:
printfn "%d" myDelta1  

let mutable myDelta2 = 10
incrementor.Increment(&myDelta2)
// Prints 11:
printfn "%d" myDelta2 

let refInt = ref 10
incrementor.Increment(refInt)
// Prints 11:
printfn "%d" !refInt

Aby uzyskać więcej informacji na temat przechodzą przez odwołanie, zobacz Parametry i argumenty (F#).

[!UWAGA]

Programistów języka C# należy wiedzieć, że ref działa w F# inaczej, niż w języku C#.Na przykład, użycie ref po przesunięciu argument nie ma ten sam efekt w F# jak w języku C#.

Odwołanie komórki vs.Tych zmiennych.

Odwoływanie się do komórek i tych zmiennych można często używane w tej samej sytuacji.Istnieją jednak pewne sytuacje, w których nie można używać tych zmiennych i komórki odniesienia należy użyć zamiast.Ogólnie rzecz biorąc należy preferować tych zmiennych, gdzie są akceptowane przez kompilator.Jednak w wyrażeniach, które generują zamknięcia, kompilator będzie sprawozdanie, że nie można użyć tych zmiennych.Zamknięcia są lokalne funkcje, które są generowane przez niektórych F# wyrażeń, takich jak lambda wyrażenia, sekwencji wyrażeń, wyrażenia obliczeń i curried funkcji, które używają częściowo stosowane argumentów.Wolnych od pracy, generowane przez te wyrażenia są przechowywane dla późniejszej ocenie.Proces ten nie jest zgodny z tych zmiennych.W związku z tym Jeśli potrzebujesz mutable Państwo w wyrażeniu jest, należy użyć odwołania komórek.Aby uzyskać więcej informacji na temat wolnych od pracy zobacz temat zamknięć (F#).

Poniższy przykład kodu pokazuje scenariusz, w którym należy użyć komórki odwołanie.

// Print all the lines read in from the console.
let PrintLines1() =
    let mutable finished = false
    while not finished do
        match System.Console.ReadLine() with
        | null -> finished <- true
        | s -> printfn "line is: %s" s


// Attempt to wrap the printing loop into a 
// sequence expression to delay the computation.
let PrintLines2() =
    seq {
        let mutable finished = false
        // Compiler error:
        while not finished do  
            match System.Console.ReadLine() with
            | null -> finished <- true
            | s -> yield s
    }

// You must use a reference cell instead.
let PrintLines3() =
    seq {
        let finished = ref false
        while not !finished do
            match System.Console.ReadLine() with
            | null -> finished := true
            | s -> yield s
    }

W poprzednim kodzie komórki odwołanie finished znajduje się w stanie lokalnych, oznacza to, zmienne, które znajdują się w zamknięcia są tworzone i używane wyłącznie w wyrażeniu, w tym przypadku wyrażenie sekwencji.Należy rozważyć, jakie występuje wówczas, gdy zmienne są nielokalnych.Wolnych od pracy można także uzyskać dostęp Państwo nielokalnych, ale w takim przypadku zmienne są kopiowane i przechowywane przez wartość.Proces ten jest znany jako semantykę wartości.Oznacza to, że wartości w czasie kopia są przechowywane i wszelkich późniejszych zmianach zmienne nie są uwzględniane.Jeśli chcesz śledzić zmiany — do lokalnych zmiennych, lub w innych wyrazów, jeśli potrzebujesz zamknięcia, który współdziała z Państwem do lokalnego przy użyciu odniesienia semantykę, należy użyć komórki odwołanie.

W poniższych przykładach kodu demonstrują użycie Ogniwa wzorcowe w wolnych od pracy.W przypadku zamknięcia wynika z częściowego stosowania argumenty funkcji.

// The following code demonstrates the use of reference
// cells to enable partially applied arguments to be changed
// by later code.

let increment1 delta number = number + delta

let mutable myMutableIncrement = 10

// Closures created by partial application and literals.
let incrementBy1 = increment1 1
let incrementBy2 = increment1 2

// Partial application of one argument from a mutable variable.
let incrementMutable = increment1 myMutableIncrement

myMutableIncrement <- 12

// This line prints 110.
printfn "%d" (incrementMutable 100)

let myRefIncrement = ref 10

// Partial application of one argument, dereferenced
// from a reference cell.
let incrementRef = increment1 !myRefIncrement

myRefIncrement := 12

// This line also prints 110.
printfn "%d" (incrementRef 100)

// Reset the value of the reference cell.
myRefIncrement := 10

// New increment function takes a reference cell.
let increment2 delta number = number + !delta

// Partial application of one argument, passing a reference cell
// without dereferencing first.
let incrementRef2 = increment2 myRefIncrement

myRefIncrement := 12

// This line prints 112.
printfn "%d" (incrementRef2 100)

Zobacz też

Informacje

Symbol i Operator odniesienia (F#)

Koncepcje

Parametry i argumenty (F#)

Inne zasoby

F# Language Reference