I riferimenti in VB.NET
-
23-08-2019 - |
Domanda
Un po 'poco chiaro a me sono riferimenti (puntatori?) Per le classi in VB.NET. La domanda che sto per chiedere può essere risolta da un po 'di prove, ma mi chiedevo se qualcuno potesse inviare una spiegazione decente (o link, troppo).
Se si crea una classe:
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
E poi una classe che in realtà utilizza questa classe come una proprietà:
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
E poi usare in questo modo:
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
Ora la funzione BooleanCheck
restituirà sempre true
, anche se è passato il riferimento alla nuova UsingClass
di classe "per valore", non con riferimento. Quindi, una copia della classe non è fatta, ma la myReference
variabile locale in UsingClass
fa ancora riferimento / punti alla Reference
proprietà a RuntimeOrSomething
.
Come può essere spiegato con eleganza?
Soluzione
A punti di riferimento a un'istanza di un oggetto, non è un'istanza di un oggetto. Fare una copia delle istruzioni per l'oggetto non crea un altro oggetto, si crea un altro riferimento che punta anche allo stesso oggetto.
Altri suggerimenti
Non riesco a mettere molto tempo in questa risposta ora - digitando su un treno con un bambino sul mio ginocchio - ma ho un paio di articoli che potrebbero aiutare. Sono scritti su C #, ma lo stesso vale per VB.NET:
MSDN :
Se si passa un argomento variabile valore utilizzando la parola chiave ByVal, il procedura non può modificare la variabile si. Tuttavia, se l'argomento è un tipo di riferimento, è possibile modificare la membri dell'oggetto a cui punti, anche se non si può sostituire l'oggetto stesso. In particolare, è può modificare i membri dell'oggetto. Ad esempio, se l'argomento è un variabile di matrice, non è possibile assegnare un nuovo array ad esso, ma si può cambiare uno o più dei suoi elementi. Il elementi modificati sono riflesse nel variabile di matrice sottostante nel chiamando codice.
Dal momento che il ReferenceClass è un tipo di riferimento, se si passa ByVal, non è possibile sostituirlo con un nuovo oggetto (che non si fa), ma si può impazzire con le sue interiora (che si fa). Se si passa ByRef o ByVal, gingillarsi con le sue interiora sarà ancora "influenzare" l'oggetto originale (poiché non v'è sempre e solo un oggetto in memoria).
In questa riga:
Dim tempClass as New UsingClass(Reference)
l'oggetto a cui si riferisce la proprietà Reference
viene passato "per valore", ma non è il oggetto che viene copiato, è il di riferimento a quell'oggetto che viene copiato (cioè MyReference e tempClass.Reference sono due "puntatori" distinti allo stesso oggetto. Si potrebbe quindi fare tempClass.Reference = new ReferenceClass
e poi MyReference e tempClass.Reference sono ancora due "puntatori" distinti, ma ora ogni punto a due oggetti diversi.
Quando si passa classi ByVal / byref in VB.NET è possibile pensare ad esso in termini di programmazione C e puntatori in modo tale che -
ByVal = passing arguments via - a pointer ByRef = passing arguments via - a pointer to a pointer
Prendere le stringhe come esempio
' 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
Come detto sopra, l'impostazione di una variabile oggetto uguale ad un altro solo imposta il "puntatore" a un'istanza dello stesso oggetto in memoria, se si desidera clonare l'aspetto oggetto in che implementa l'interfaccia ICloneable con qualcosa di simile
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function
Con e quando l'oggetto di allocazione utilizzare il metodo clone
Dim tempClass as ReferenceClass = Reference.Clone