Références dans VB.NET
-
23-08-2019 - |
Question
Les références (pointeurs?) À VB.NET sont un peu peu difficiles. La question que je suis sur le point de poser peut être répondue par un peu de test, mais je me demandais si quelqu'un pouvait afficher une explication (ou des liens aussi).
Si vous créez une 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
Et puis une classe qui utilise réellement cette classe comme propriété:
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
Et puis utilisez-le comme ceci:
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
Maintenant la fonction BooleanCheck
reviendra toujours true
, même si la référence est transmise à la nouvelle classe UsingClass
"par valeur", non par référence. Donc une copie de la classe n'est pas faite, mais la variable locale myReference
dans UsingClass
toujours références / pointes à la propriété Reference
dans RuntimeOrSomething
.
Comment cela peut-il être expliqué avec élégance?
La solution
Une référence pointe vers une instance d'un objet, ce n'est pas une instance d'un objet. Faire une copie des directions vers l'objet ne crée pas un autre objet, il crée une autre référence qui pointe également vers le même objet.
Autres conseils
Je ne peux pas consacrer beaucoup de temps à cette réponse maintenant - taper dans un train avec un tout-petit sur mon genou - mais j'ai quelques articles qui pourraient aider. Ils sont écrits sur C #, mais il en va de même pour VB.NET:
De MSDN:
Si vous transmettez un argument de variable par valeur à l'aide du mot clé ByVal, la procédure ne peut pas modifier la variable elle-même. Cependant, si l'argument est un type de référence, vous pouvez modifier les membres de l'objet auxquels il pointe, même si vous ne pouvez pas remplacer l'objet lui-même. En particulier, vous pouvez modifier les membres de l'objet. Par exemple, si l'argument est une variable de tableau, vous ne pouvez pas y attribuer un nouveau tableau, mais que vous pouvez modifier un ou plusieurs de ses éléments. Les éléments modifiés sont reflétés dans la variable de tableau sous-jacente dans le code d'appel.
Étant donné que votre référence est un type de référence, si vous le transmettez par ByVal, vous ne pouvez pas le remplacer par un nouvel objet (que vous ne le faites pas), mais vous pouvez fouiller avec ses entrailles (ce que vous faites). Que vous passiez ByRef ou Byval, se détendre avec ses entrailles "affectera toujours" l'objet d'origine (car il n'y a jamais un seul objet en mémoire).
Dans cette ligne:
Dim tempClass as New UsingClass(Reference)
l'objet mentionné par le Reference
la propriété est transmise "par valeur", mais ce n'est pas le objet qui est copié, C'est le référence à cet objet qui est copié (ie myreference et tempclass. tempClass.Reference = new ReferenceClass
Et puis MyReference et TempClass.Reference sont encore deux "pointeurs" distincts, mais maintenant ils pointent chacun vers deux objets différents.
Lorsque vous passez des classes BYVAL / BYREF dans VB.NET, il est possible de le penser en termes de programmation C et de pointeurs de telle sorte que -
ByVal = passing arguments via - a pointer ByRef = passing arguments via - a pointer to a pointer
Prenez des cordes comme exemple
' 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
Comme dit ci-dessus, définir une variable d'objet égale à un autre définit simplement le "pointeur" sur une instance du même objet en mémoire, si vous souhaitez cloner l'objet, envisagez d'implémenter l'interface iclonable avec quelque chose comme
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function
Avec et lorsque vous allocation de l'objet utilisez la méthode de clone
Dim tempClass as ReferenceClass = Reference.Clone