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 中的引用的主要内容,如果未能解决你的问题,请参考以下文章