在 Visual Basic 中,通常需要创建对象的副本,以便以新的方式修改数据,而不影响原始结构。必须区分浅复制(shallow)和深复制(deep),特别是当对象包含嵌套引用类型时。
问题背景:
浅复制只复制原始属性的值和对嵌套对象的引用,而深复制则为所有嵌套对象创建新的实例。在处理复杂数据时,这种区别至关重要,例如,如果对象包含集合或其他对象。
问题:
如果通过引用复制对象或使用标准方法 MemberwiseClone,则在更改嵌套对象时,原始结构也会随副本一起更改——这对业务逻辑来说是危险的,可能导致难以捕捉的bug。
解决方案:
在 VB.NET 中,没有直接的深复制实现,因此需要手动实现或通过序列化进行实现。通常通过创建新的嵌套对象实例来实现用户自定义的 DeepCopy 方法。
浅复制和深复制的示例代码:
Class Person Public Name As String Public Address As Address ' 浅复制 Public Function ShallowCopy() As Person Return CType(Me.MemberwiseClone(), Person) End Function ' 深复制 Public Function DeepCopy() As Person Dim copy As Person = CType(Me.MemberwiseClone(), Person) copy.Address = New Address() With {.City = Me.Address.City} Return copy End Function End Class Class Address Public City As String End Class
关键特点:
在 Visual Basic 中,复制类对象时,操作符 = 会返回什么?
答案:对于引用类型,操作符 = 赋值的是引用,而不是复制值。因此两个变量将指向同一个对象。
Dim a As New Person() Dim b As Person = a ' 现在 a 和 b 是指向同一个对象的引用
可以使用 MemberwiseClone 进行深复制吗?
答案:不可以。方法 MemberwiseClone 仅实现浅复制——所有嵌套引用类型按引用复制。
为什么序列化并不总是深复制的通用方法?
答案:序列化仅适用于可序列化对象,可能不支持 Object 类型的属性或未标记为 Serializable 的属性。此外,序列化的速度比标准复制要慢。
客户通过操作符 = 复制订单对象以创建新订单,而不知道嵌套的项目列表仍然是两个对象共享的一个。
优点: 快速,简单
缺点: 一个订单的更改会影响另一个订单——在库存管理中出现严重错误。
实现了 DeepCopy 方法以复制订单及其所有嵌套商品和送货地址。
优点: 数据的可靠分离,正确的业务逻辑
缺点: 需要密切关注对象结构,需要更多的支持代码