Ссылки в VB.NET
-
23-08-2019 - |
Вопрос
Мне несколько неясно, есть ли ссылки (указатели?) К классам в vb.net. На вопрос, который я собираюсь задать, можно ответить на небольшое тестирование, но мне было интересно, может ли кто -нибудь опубликовать достойное объяснение (или ссылки тоже).
Если вы создаете класс:
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
А потом класс, который фактически использует этот класс в качестве свойства:
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
А потом используйте это так:
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
Теперь функция BooleanCheck
всегда вернется true
, хотя ссылка передается в новый класс UsingClass
«По значению», а не по ссылке. Таким образом, копия класса не сделана, а локальная переменная myReference
в UsingClass
все еще ссылки/указывают на собственность Reference
в RuntimeOrSomething
.
Как это можно объяснить элегантно?
Решение
Ссылка указывает на экземпляр объекта, это не экземпляр объекта. Создание копии указаний в объект не создает другого объекта, он создает другую ссылку, которая также указывает на тот же объект.
Другие советы
Сейчас я не могу потратить много времени на этот ответ - набрать поезд с малышом на колене - но у меня есть пара статей, которые могут помочь. Они написаны о C#, но то же самое относится и к VB.net:
Из MSDN:
Если вы передаете аргумент переменной путем значения, используя ключевое слово Byval, процедура не может изменить саму переменную. Однако, если аргумент является ссылочным типом, вы можете изменить членов объекта, на который он указывает, даже если вы не можете заменить сам объект. В частности, вы можете изменить членов объекта. Например, если аргумент является переменной массива, вы не можете присвоить ему новый массив, но вы можете изменить один или несколько его элементов. Измененные элементы отражаются в основной переменной массива в вызовом коде.
Поскольку ваш ссылки является ссылочным типом, если вы передаете его Byval, вы не можете заменить его новым объектом (которого вы не делаете), но вы можете разбить его внутренностями (что вы делаете). Независимо от того, проходите ли вы ByRef или Byval, пронзительство с его внутренностями все еще «повлияет» на исходный объект (поскольку в памяти есть только один объект).
В этой линии:
Dim tempClass as New UsingClass(Reference)
объект, на который упоминается Reference
собственность передается «стоимостью», но это не объект это скопировано, это ссылка к этому объекту, который скопирован (т. Е. MyReference и TempClass.Reference - это два различных «указателя» для одного и того же объекта. Вы можете тогда сделать tempClass.Reference = new ReferenceClass
И затем MyReference и Tempclass.Reference все еще являются двумя различными «указателями», но теперь каждый указывает на два разных объекта.
При прохождении классов Byval/Byref в vb.net можно подумать об этом с точки зрения программирования C и указателей, таких как -
ByVal = passing arguments via - a pointer ByRef = passing arguments via - a pointer to a pointer
Принять струны в качестве примера
' 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
Как сказано выше, настройка переменной объекта, равная другой, просто устанавливает «указатель» на экземпляр одного и того же объекта в памяти, если вы хотите клонировать объект, посмотрите на реализацию интерфейса Iclonable с чем -то вроде
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function
С и когда вы распределяете, объект использует метод клона
Dim tempClass as ReferenceClass = Reference.Clone