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

现在函数BooleanCheck将始终返回true,即使引用是UsingClass“按值”而不是按引用传递给新类的。因此,没有制作类的副本,但myReferencein 中的局部变量UsingClass仍然引用/指向Reference.RuntimeOrSomething

这怎么能优雅地解释呢?

4

6 回答 6

8

引用指向对象的实例,它不是对象的实例。复制到对象的方向不会创建另一个对象,它会创建另一个也指向同一对象的引用。

于 2008-12-23T17:32:44.047 回答
7

我现在不能花太多时间来回答这个问题——在火车上打字,膝盖上有一个蹒跚学步的孩子——但我有几篇文章可能会有所帮助。它们是关于 C# 的,但同样适用于 VB.NET:

于 2008-12-23T17:25:49.570 回答
2

来自MSDN

如果使用 ByVal 关键字按值传递变量参数,则过程不能修改变量本身。但是,如果参数是引用类型,您可以修改它指向的对象的成员,即使您不能替换对象本身。特别是,您可以修改对象的成员。例如,如果参数是数组变量,则不能为其分配新数组,但可以更改其一个或多个元素。更改的元素反映在调用代码中的底层数组变量中。

由于您的 ReferenceClass 是一个引用类型,如果您通过 ByVal 传递它,则不能用新对象(您没有)替换它,但您可以用它的内部(您做的)乱七八糟。无论你通过 ByRef 还是 ByVal,乱搞它的内脏仍然会“影响”原始对象(因为内存中只有一个对象)。

于 2008-12-23T20:08:08.993 回答
1

在这一行:

Dim tempClass as New UsingClass(Reference)

属性引用的对象Reference是“按值”传递的,但它不是被复制的对象,而是对被复制对象引用(即 myReference 和 tempClass.Reference 是指向同一对象的两个不同的“指针”。然后你可以这样做tempClass.Reference = new ReferenceClassmyReference 和 tempClass.Reference 仍然是两个不同的“指针”,但现在它们每个都指向两个不同的对象。

于 2008-12-23T18:44:35.667 回答
1

在 VB.NET 中传递类 byval/byref 时,可以根据 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
于 2008-12-23T19:20:49.430 回答
0

如上所述,设置一个对象变量等于另一个只是将“指针”设置为内存中同一对象的一个​​实例,如果你想克隆对象看看实现 iCloneable 接口类似

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

分配对象时使用克隆方法

Dim tempClass as ReferenceClass = Reference.Clone
于 2008-12-28T08:46:30.720 回答