Referências em vb.net
-
23-08-2019 - |
Pergunta
Um pouco claro para mim são referências (ponteiros?) Para aulas no vb.net. A pergunta que estou prestes a fazer pode ser respondida por um pouco de teste, mas eu queria saber se alguém poderia postar uma explicação decente (ou links também).
Se você criar uma 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 então uma classe que realmente usa esta classe como uma propriedade:
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 então use assim:
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
Agora a função BooleanCheck
sempre voltará true
, mesmo que a referência seja passada para a nova classe UsingClass
"Por valor", não por referência. Portanto, uma cópia da classe não é feita, mas a variável local myReference
dentro UsingClass
ainda referências/pontos para a propriedade Reference
dentro RuntimeOrSomething
.
Como isso pode ser explicado elegantemente?
Solução
Uma referência aponta para uma instância de um objeto, não é uma instância de um objeto. Fazer uma cópia das instruções para o objeto não cria outro objeto, ele cria outra referência que também aponta para o mesmo objeto.
Outras dicas
Não posso dedicar muito tempo a essa resposta agora - digitando um trem com uma criança no meu joelho - mas tenho alguns artigos que podem ajudar. Eles estão escritos sobre C#, mas o mesmo se aplica ao VB.NET:
A partir de Msdn:
Se você passar em um argumento variável por valor usando a palavra -chave BYVAL, o procedimento não poderá modificar a própria variável. No entanto, se o argumento for um tipo de referência, você poderá modificar os membros do objeto ao qual ele aponta, mesmo que você não possa substituir o próprio objeto. Em particular, você pode modificar os membros do objeto. Por exemplo, se o argumento for uma variável de matriz, você não poderá atribuir uma nova matriz, mas poderá alterar um ou mais de seus elementos. Os elementos alterados são refletidos na variável de matriz subjacente no código de chamada.
Como o seu referenceClass é um tipo de referência, se você o passar pelo BYVAL, não poderá substituí -lo por um novo objeto (o que você não faz), mas poderá se movimentar com suas entranhas (o que você faz). Se você passa por Byref ou Byval, misturando com suas entranhas ainda "afetará" o objeto original (já que existe apenas um objeto na memória).
Nesta linha:
Dim tempClass as New UsingClass(Reference)
o objeto referido pelo Reference
a propriedade é aprovada "por valor", mas não é o objeto que é copiado, é o referência para esse objeto que é copiado (isto tempClass.Reference = new ReferenceClass
E então MyReference e TempClass.Reference ainda são dois "ponteiros" distintos, mas agora cada um aponta para dois objetos diferentes.
Ao passar as aulas BYVAL/BYREF em VB.NET, é possível pensar nisso em termos de programação e indicadores de tal forma que -
ByVal = passing arguments via - a pointer ByRef = passing arguments via - a pointer to a pointer
Tome cordas como exemplo
' 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 dito acima, definir uma variável de objeto igual a outro apenas define o "ponteiro" para uma instância do mesmo objeto na memória, se você quiser clonar o objeto, veja a implementação da interface iCloneable com algo como
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function
Com e quando você alocando o objeto, use o método clone
Dim tempClass as ReferenceClass = Reference.Clone