La comprensión de byref, ref y &
-
14-11-2019 - |
Pregunta
Bien, llegué a entender que F# es capaz de administrar las referencias (una especie de C++ como referencias).Esto permite que las posibilidades para cambiar el valor de los parámetros pasados en funciones y también permite al programador a devolver más de un valor único.Sin embargo, aquí es lo que necesito saber:
Palabra clave Ref:La palabra clave
ref
se utiliza para crear, a partir de un valor, una referencia a que el valor del tipo inferido.Asílet myref = ref 10
Esto significa que F# crear un objeto de tipo
Ref<int>
poniendo allí (en el mutable campo) miint 10
.OK.Así que supongo que
ref
se utiliza para crear instancias de laRef<'a>
tipo.Es correcto?El acceso valor:Para poder acceder a un valor almacenado en referencia puedo hacer esto:
let myref = ref 10 let myval = myref.Value let myval2 = !myref
Mientras que el
:=
operador solo me permite editar el valor como este:let myref = ref 10 myref.Value <- 30 myref := 40
Así
!
(Bang) desreferencias mi referencia.Y:=
editarlo.Supongo que esto es correcto también.El operador&:Lo que hace este operador hacer?Es que se aplique a un tipo de referencia?No, supongo que debe ser aplicado a un mutable valor y devuelve qué?La referencia?La dirección?Si el uso interactivo:
let mutable mutvar = 10;; &a;;
La última línea se produce un error, así que no entiendo lo que el
&
el operador se para.ByRef:¿Qué acerca de
byref
?Eso es muy importante para mí, pero me doy cuenta de que yo no lo entiendo.Entiendo que es utilizado en función de la relación de paso de parámetros.Uno de los usos byref cuando se quiere que el valor pasado puede ser editado (esto es un poco en contra de los lenguajes funcionales de la filosofía, pero f# es algo más que eso).Considere lo siguiente:let myfunc (x: int byref) = x <- x + 10
Esto es extraño.Yo sé que si usted tiene un de referencia de la
let myref = ref 10
y, a continuación, hacer esto para modificar el valor:myref <- 10
surge un error porque debe ser como esto:myref := 10
.Sin embargo, el hecho de que en esa función que puedo editarx
el uso de la<-
operador de medios quex
no es una referencia, a la derecha?Si asumo que
x
no es una referencia, entonces supongo también que, en las funciones, cuando se utilizabyref
en un parámetro, el parámetro puede tener los mutables sintaxis aplicada.Así que es sólo una cuestión de sintaxis, si supongo esto estoy bien, y, de hecho, todo funciona (no hay errores de compilación).Sin embargo, lo que esx
?Las llamadas a las funciones:¿Cómo puedo utilizar una función utilizando los parámetros de byref?
El
&
operador está involucrado, pero podría usted explicar esto mejor, por favor?En este artículo: MSDN Parámetros y Argumentos se brinda el siguiente ejemplo: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
Solución
Palabra clave Ref Sí, cuando usted escribe let a = ref 10
básicamente estás escribiendo let a = new Ref<int>(10)
donde el Ref<T>
el tipo tiene un mutable campo Value
.
El acceso valor El :=
y !
los operadores son atajos para escribir:
a.Value <- 10 // same as writing: a := 10
a.Value // same as writing: !a
ByRef es un tipo especial que puede ser (razonablemente) se utiliza sólo en los parámetros del método.Esto significa que el argumento debe ser esencialmente un puntero a algunos ubicación de la memoria (asignado en montón o pila).Corresponde a out
y ref
modificadores en C#.Tenga en cuenta que usted no puede crear una variable local de este tipo.
El operador & es una forma de crear un valor (un puntero) que puede ser pasado como argumento a una función/método esperando un byref
tipo.
Las llamadas a las funciones el ejemplo con byref
funciona porque estás pasando el método de una referencia a una variable mutable.A través de la referencia, el método puede cambiar el valor almacenado en la variable.
La siguiente no funciona:
let a = 10 // Note: You don't even need 'mutable' here
bar.Increment(ref a)
La razón es que estamos creando una nueva instancia de Ref<int>
y va a copiar el valor de a
en esta instancia.El Increment
método, a continuación, modifica el valor almacenado en la pila en la instancia de Ref<int>
, pero usted no tiene una referencia a este objeto más.
let a = ref 10
bar.Increment(a)
Esto funciona, porque a
es un valor de tipo Ref<int>
y estás pasando un puntero a la asigna el montón de instancia para Increment
y, a continuación, obtener el valor de asigna el montón de referencia de celda utilizando !a
.
(Usted puede usar los valores creados mediante ref
como argumentos para byref
porque el compilador se encarga de esto caso especialmente - automáticamente se tome de referencia de la Value
de campo porque se trata de un útil escenario...).