VB.NET 中的引用

Posted

技术标签:

【中文标题】VB.NET 中的引用【英文标题】:References in VB.NET 【发布时间】:2010-09-28 05:08:00 【问题描述】:

对我来说有些不清楚的是对 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。因此没有制作类的副本,但UsingClass 中的局部变量myReference 仍然引用/指向RuntimeOrSomething 中的属性Reference

如何优雅地解释这一点?

【问题讨论】:

【参考方案1】:

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

Reference types and value types Parameter passing in .NET

【讨论】:

哦,Skeet 先生,我相信您已经对 SOFlow 的答案上瘾了。 8^D 谢谢,好文章现在在我的“catch-up-reading-list”之上:-)【参考方案2】:

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

【讨论】:

谢谢,您是第一个给出简单明了的解释的人。 这个原则有一个奇怪的例外:如果有问题的引用指向一个装箱的非原始值类型,并且如果赋值的源类型和目标类型是Object,那么对于一些原因 VB.NET 将存储对对象副本的引用,而不是对原始对象的引用。【参考方案3】:

在这一行:

Dim tempClass as New UsingClass(Reference)

Reference 属性引用的对象是“按值”传递的,但它不是复制的 object它是 reference复制的对象(即 myReference 和 tempClass.Reference 是指向同一个对象的两个不同的“指针”。然后您可以执行 tempClass.Reference = new ReferenceClass 然后 myReference 和 tempClass.Reference 仍然是两个不同的“指针”,但是现在它们每个都指向两个不同的对象。

【讨论】:

【参考方案4】:

在 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

【讨论】:

【参考方案5】:

来自MSDN:

如果你传递一个变量参数 使用 ByVal 关键字的值, 程序不能修改变量 本身。 但是,如果参数是 引用类型,可以修改 它所针对的对象的成员 点,即使你不能替换 对象本身。 特别是,您 可以修改对象的成员。 例如,如果参数是 数组变量,你不能分配一个 新数组,但你可以改变 它的一个或多个元素。这 变化的元素反映在 底层数组变量 调用代码。

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

【讨论】:

感谢 msdn 链接,不知怎的,我在之前的访问和搜索中完全错过了该链接【参考方案6】:

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

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

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

Dim tempClass as ReferenceClass = Reference.Clone

【讨论】:

以上是关于VB.NET 中的引用的主要内容,如果未能解决你的问题,请参考以下文章

vb.net 如何引用自定义类库

从 VB.Net DLL 引用 DLL

我可以将类引用作为参数传递给 VB Net 中的函数吗?

vb.net引用Dll的问题

.net中如何引用Dll文件?

VB.Net & Access - 设置两个外键,引用同一个表/字段