Referencias en VB.NET
-
23-08-2019 - |
Pregunta
Un poco poco claro para mí hay referencias (¿Pointers?) A las clases en VB.NET. La pregunta que estoy a punto de hacer puede ser respondida por un poco de pruebas, pero me preguntaba si alguien podría publicar una explicación decente (o enlaces también).
Si crea una clase:
Public Class ReferenceClass
Private myBooleanValue As Boolean = False
Public Property BooleanValue As Boolean
Get
Return myBooleanValue
End Get
Set(value As Boolean)
myBooleanValue = value
End Set
End Property
End Class
Y luego una clase que realmente usa esta clase como propiedad:
Public Class UsingClass
Private myReference As ReferenceClass
Public Property Reference As ReferenceClass
Get
return myReference
End Get
Set(value As ReferenceClass)
myReference = value
End Set
End Property
Public Sub New(ByVal Reference As ReferenceClass)
myReference = Reference
End Sub
End Class
Y luego úsalo así:
Public Class RuntimeOrSomething
Public Shared myReference As ReferenceClass
Public Shared ReadOnly Property Reference As ReferenceClass
Get
If myReference Is Nothing Then myReference = new ReferenceClass()
return myReference
End Get
End Property
Public Shared Function BooleanCheck() As Boolean
Reference.BooleanValue = True
Dim tempClass As New UsingClass(Reference)
tempClass.Reference.BooleanValue = False
Return (tempClass.Reference.BooleanValue = Reference.BooleanValue)
End Sub
Public Shared Sub DoNothing()
Reference.BooleanValue = True
Dim someBoolean As Boolean = BooleanCheck
' Now Reference.Booleanvalue is "False"
End Sub
End Class
Ahora la función BooleanCheck
siempre volverá true
, a pesar de que la referencia se pasa a la nueva clase UsingClass
"Por valor", no por referencia. Entonces no se hace una copia de la clase, sino la variable local myReference
en UsingClass
aún referencias/puntos a la propiedad Reference
en RuntimeOrSomething
.
¿Cómo se puede explicar esto elegantemente?
Solución
Una referencia apunta a una instancia de un objeto, no es una instancia de un objeto. Hacer una copia de las instrucciones al objeto no crea otro objeto, crea otra referencia que también apunta al mismo objeto.
Otros consejos
No puedo dedicar mucho tiempo a esta respuesta, escribiendo en un tren con un niño pequeño en la rodilla, pero tengo un par de artículos que podrían ayudar. Están escritos sobre C#, pero lo mismo se aplica a VB.NET:
De MSDN:
Si pasa un argumento variable por valor utilizando la palabra clave BYVAL, el procedimiento no puede modificar la variable misma. Sin embargo, si el argumento es un tipo de referencia, puede modificar los miembros del objeto al que señala, aunque no puede reemplazar el objeto en sí. En particular, puede modificar los miembros del objeto. Por ejemplo, si el argumento es una variable de matriz, no puede asignarle una nueva matriz, pero puede cambiar uno o más de sus elementos. Los elementos cambiados se reflejan en la variable de matriz subyacente en el código de llamada.
Dado que su referenceClass es un tipo de referencia, si lo pasa, no puede reemplazarlo con un nuevo objeto (que no lo hace), pero puede meterse con sus entrañas (lo que hace). Ya sea que pase Byref o Byval, se mueve con sus entrañas aún "afectará" al objeto original (ya que solo hay un objeto en la memoria).
En esta línea:
Dim tempClass as New UsingClass(Reference)
el objeto referido por el Reference
la propiedad se pasa "por valor", pero no es el objeto que se copia, es el referencia a ese objeto que se copia (es decir, myreference y tempclass.reference son dos "punteros" distintos al mismo objeto. Entonces podrías hacer tempClass.Reference = new ReferenceClass
Y luego MyReference y Tempclass.Reference siguen siendo dos "punteros" distintos, pero ahora cada uno apuntan a dos objetos diferentes.
Al pasar las clases BYVAL/BYREF en VB.NET, es posible pensar en ello en términos de programación C y punteros de tal manera que -
ByVal = passing arguments via - a pointer ByRef = passing arguments via - a pointer to a pointer
Tome cuerdas como ejemplo
' ByRef - modify str pointer to "point" to a new string
Sub Test_Ref(ByRef str as string)
str = "New String ByRef"
End Sub
' ByVal - can't modify str pointer must return a (pointer to) new string
Function Test_Val(ByVal str as String) as String
Return "New String ByVal"
End Sub
Sub Main()
Dim strTest as String = "Hello World!"
Console.WriteLine(strTest)
Test_Ref(strTest)
Console.WriteLine(strTest)
Test_Val(strTest)
Console.WriteLine(strTest) ' oops still pointing to same string
strTest = Test_Val(strTest)
Console.WriteLine(strTest) ' that's better :)
End Sub
Como se dijo anteriormente, establecer una variable de objeto igual a otra simplemente establece el "puntero" en una instancia del mismo objeto en la memoria, si desea clonar el objeto, busque la implementación de la interfaz iCLonable con algo como
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function
Con y cuando se asigna el objeto usa el método clon
Dim tempClass as ReferenceClass = Reference.Clone