VB.NET中的引用

3

对于我来说,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

现在,即使将引用按“按值”方式传递给新类UsingClass,函数BooleanCheck也始终返回true。因此,不会创建类的副本,但是UsingClass中的局部变量myReference仍然引用/指向RuntimeOrSomething中的属性Reference。如何优雅地解释这一点呢?
6个回答

8

引用是指向对象实例的一个指针,它本身不是对象实例。复制对象的指针并不会创建另一个对象实例,而是创建另一个指向同一对象的引用。


谢谢,你是第一个给出简单明了解释的人。 - Jorrit Reedijk
2
有一个奇怪的例外原则:如果所涉及的引用指向装箱的非基元值类型,并且赋值的源类型和目标类型是 Object,那么由于某种原因,VB.NET 将存储对对象副本的引用,而不是对原始对象的引用。 - supercat

7

我现在无法花太多时间回答这个问题 - 我正在火车上打字,膝盖上还有一个小孩 - 但是我有几篇文章可能会有所帮助。它们是关于C#的,但同样适用于VB.NET:


3
哦,Skeet先生,我相信你真的对那个答案上了瘾,因为你的回答证明了这一点。8^D - Dillie-O
谢谢,这些很棒的文章现在已经在我“待读清单”的顶部了 :-) - Jorrit Reedijk

2
来自 MSDN
如果你使用 ByVal 关键字将可变参数按值传递,那么过程无法修改变量本身。然而,如果参数是引用类型,即使不能替换对象本身,也可以修改指向的对象的成员。特别地,可以修改对象的成员。例如,如果参数是一个数组变量,则无法将新数组分配给它,但可以更改其中一个或多个元素。更改后的元素会反映在调用代码中的基础数组变量中。
由于 ReferenceClass 是引用类型,如果你按值传递它,就不能用一个新对象替换它(实际上你不需要这么做),但是你可以修改它的内部。无论你是按引用还是按值传递,都会“影响”原始对象(因为内存中只有一个对象)。

1
感谢提供 MSDN 链接,我之前在那里的访问和搜索中完全错过了它。 - Jorrit Reedijk

1
在VB.NET中传递类时,可以将其视为C编程和指针的术语,如下所示:
ByVal = 通过指针传递参数 ByRef = 通过指向指针的指针传递参数
以字符串为例。
' 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

在这一行中:

Dim tempClass as New UsingClass(Reference)

Reference属性所引用的对象是"按值"传递的,但复制的不是对象本身,而是指向该对象的引用(即myReference和tempClass.Reference是对同一对象的两个不同"指针"。然后,您可以执行tempClass.Reference = new ReferenceClass,然后myReference和tempClass.Reference仍然是两个不同的"指针",但现在它们各自指向两个不同的对象。


0
如上所述,将一个对象变量设置为另一个对象只是将“指针”设置为内存中相同对象的实例,如果您想克隆该对象,请查看使用iCloneable接口实现类似以下内容的内容。
Public Function Clone() As Object Implements ICloneable.Clone
Return Me.MemberwiseClone()
End Function

在分配对象时,请使用克隆方法。

Dim tempClass as ReferenceClass = Reference.Clone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接