Ссылки в VB.NET

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
7 783
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

О, мистер Скит, я считаю, что вы ДЕЙСТВИТЕЛЬНО пристрастились к SOFlow с таким ответом прямо здесь. 8 ^ D

Dillie-O 23.12.2008 20:27

спасибо, хорошие статьи, которые теперь в моем "списке для чтения" :-)

Jorrit Reedijk 25.12.2008 03:35
Ответ принят как подходящий

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

спасибо, вы были первым с простым и понятным объяснением.

Jorrit Reedijk 25.12.2008 03:34

Есть любопытное исключение из этого принципа: если рассматриваемая ссылка указывает на упакованный непримитивный тип значения, и если тип источника и тип назначения назначения - Object, то по какой-то причине VB.NET сохранит ссылку на копия объекта, а не оригинал.

supercat 03.08.2013 01:41

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

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

От MSDN:

If you pass a variable argument by value using the ByVal keyword, the procedure cannot modify the variable itself. However, if the argument is a reference type, you can modify the members of the object to which it points, even though you cannot replace the object itself. In particular, you can modify the members of the object. For example, if the argument is an array variable, you cannot assign a new array to it, but you can change one or more of its elements. The changed elements are reflected in the underlying array variable in the calling code.

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

спасибо за ссылку msdn, я как-то полностью пропустил это во время предыдущих посещений и поисков там

Jorrit Reedijk 25.12.2008 03:40

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

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

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

Dim tempClass as ReferenceClass = Reference.Clone

Другие вопросы по теме