Ссылки в VB.NET - PullRequest
       54

Ссылки в VB.NET

2 голосов
/ 23 декабря 2008

Мне не совсем понятны ссылки (указатели?) На классы в 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.

Как это можно объяснить элегантно?

Ответы [ 6 ]

7 голосов
/ 23 декабря 2008

Ссылка указывает на экземпляр объекта, это не экземпляр объекта. Создание копии указаний к объекту не создает другого объекта, оно создает другую ссылку, которая также указывает на тот же объект.

6 голосов
/ 23 декабря 2008

Я не могу сейчас уделять много времени этому ответу - печатать на поезде с малышом на колене - но у меня есть пара статей, которые могут помочь. Они написаны о C #, но то же самое относится и к VB.NET:

2 голосов
/ 23 декабря 2008

С MSDN :

Если вы передаете переменный аргумент значение с помощью ключевого слова ByVal, процедура не может изменить переменную сам. Однако, если аргумент тип ссылки, вы можете изменить члены объекта, к которому это очки, даже если вы не можете заменить сам объект. В частности, вы может изменить члены объекта. Например, если аргумент является переменная массива, вы не можете назначить новый массив к нему, но вы можете изменить один или несколько его элементов. измененные элементы отражаются в лежащая в основе переменная массива в телефонный код.

Поскольку ваш ReferenceClass является ссылочным типом, если вы передадите ему ByVal, вы не сможете заменить его новым объектом (чего у вас нет), но вы можете обойти его внутренностями (что вы делаете). Независимо от того, передаете ли вы ByRef или ByVal, перебор с его внутренностями все равно будет «влиять» на исходный объект (так как в памяти только один объект).

1 голос
/ 23 декабря 2008

При передаче классов byval / byref в VB.NET это можно рассматривать с точки зрения программирования на C и указателей, что -

ByVal = passing arguments via - a pointer 
ByRef = passing arguments via - a pointer to a pointer

Взять в качестве примера строки 100 *

' 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
1 голос
/ 23 декабря 2008

В этой строке:

Dim tempClass as New UsingClass(Reference)

объект, на который ссылается свойство Reference, передается "по значению", но копируется не объект , это ссылка на этот объект который копируется (т.е. myReference и tempClass.Reference являются двумя разными «указателями» на один и тот же объект. Затем вы можете сделать tempClass.Reference = new ReferenceClass, а затем myReference и tempClass.Reference по-прежнему являются двумя разными «указателями», но теперь каждый из них указывают на два разных объекта.

0 голосов
/ 28 декабря 2008

Как сказано выше, установка переменной объекта, равной другой, просто устанавливает «указатель» на экземпляр того же объекта в памяти, если вы хотите клонировать объект, смотрящий на реализацию интерфейса iCloneable, с чем-то вроде

Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function

С и при выделении объекта используйте метод клонирования

Dim tempClass as ReferenceClass = Reference.Clone
...