创建此对象的"克隆",而不是指向它

Vol*_*ort 9 vb.net visual-studio

假设我得到了一个名单

myFirstList
Run Code Online (Sandbox Code Playgroud)

然后我想创建该列表的副本,以便我可以做一些自己的调整.所以我这样做:

mySecondList = myFirstList
mySecondList.doTweaks
Run Code Online (Sandbox Code Playgroud)

但我注意到调整也会影响myFirstList对象!我只希望调整影响第二个......

然后我想彻底删除mySecondList,所以我这样做mySecondList = Nothing,我很好,对吧?

小智 10

Adam Rackis,我不喜欢你的"当然它确实如此",因为它根本不是很明显.

如果您有一个字符串变量,您将其分配给另一个字符串变量,则在对其中一个字符串变量进行更改时不会更改它们.它们并没有指向相同的物理内存,所以为什么类很明显呢?

而且,事情甚至不一致.在下面的例子中,您将使数组中的所有元素指向同一个对象(它们最终都将变量Number设置为10:

SourceObject = New SomeClass
For i = 1 To 10
   SourceObject.Number = i
   ObjectArray.Add = SourceObject   
Next i
Run Code Online (Sandbox Code Playgroud)

但是,以下内容将为您提供10个不同的实例:

For i = 1 To 10
   SourceObject = New SomeClass
   SourceObject.Number = i
   ObjectArray.Add = SourceObject   
Next i
Run Code Online (Sandbox Code Playgroud)

显然,对象的范围有所不同,所以发生的事情并不明显.

  • 是的,对我来说,这似乎总是违反直觉.令人惊讶的是,10年后仍然没有任何简单的.NET函数或方法来进行深度克隆.2002年,当.NET出现时,好的记忆很珍贵,但现在呢? (3认同)

Ada*_*kis 6

但我注意到调整也会影响myFirstList对象!我只希望调整影响第二个......

当然可以.两个变量都指向内存中的同一个对象.你对那个做的任何事都发生在另一个.

根据您的要求,您将需要进行深度克隆或浅层克隆. 本文应该让您更好地了解您需要做什么


Bal*_*a R 6

由于您没有泄露您在列表中存储的项目类型,我认为它正在实现IClonable(否则,如果可以,可以实现IClonable,或者想出一种方法来克隆列表中的单个项目).

尝试这样的事情

mySecondList = myFirstList.[Select](Function(i) i.Clone()).ToList()
Run Code Online (Sandbox Code Playgroud)


wav*_*rop 5

扩展Adam Rackies的回答,我能够使用 VB.NET 实现以下代码。

我的目标是复制一个主要用作数据传输对象(即数据库数据)的对象列表。 首先定义了类dtoNamedClass并添加了ShallowCopy方法。创建了一个名为dtoNamedClassCloneVar的新变量,并使用 LINQ 选择查询来复制对象变量 dtoNamedClassVar。

我能够更改dtoNamedClassCloneVar不影响dtoNamedClassVar

Public Class dtoNamedClass


    ... Custom dto Property Definitions



  Public Function ShallowCopy() As dtoNamedClass
    Return DirectCast(Me.MemberwiseClone(), dtoNamedClass)
  End Function

End Class


Dim dtoNamedClassVar As List(Of dtoNamedClass) = {get your database data}

Dim dtoNamedClassCloneVar = 
    (From d In Me.dtoNamedClass
        Where {add clause if necessary}
        Select d.ShallowCopy()).ToList
Run Code Online (Sandbox Code Playgroud)


小智 5

这是你如何做到的:

'copy one object to another via reflection properties
For Each p As System.Reflection.PropertyInfo In originalobject.GetType().GetProperties()
    If p.CanRead Then
        clone.GetType().GetProperty(p.Name).SetValue(clone, p.GetValue(OriginalObject, Nothing))
    End If
Next
Run Code Online (Sandbox Code Playgroud)

在某些情况下,当克隆对象获得只读属性时,您需要先检查它。

For Each p As System.Reflection.PropertyInfo In originalobject.GetType().GetProperties()
    If p.CanRead AndAlso clone.GetType().GetProperty(p.Name).CanWrite Then
        clone.GetType().GetProperty(p.Name).SetValue(clone, p.GetValue(OriginalObject, Nothing))
    End If
Next
Run Code Online (Sandbox Code Playgroud)