从列表中获取项目作为新副本(不作为对原始文档的引用)

时间:2015-04-02 07:01:04

标签: vb.net list

如何从列表中获取项目作为新的副本/实例,以便我可以在以后使用和更改它而不更改列表中的原始对象?

Public Class entry
    Public val As String
     ' ... other fields ...
End Class

Dim MyList As New List(Of entry)
Dim newitem As New entry
newitem.val = "first"
MyList.Add(newitem)

现在,如果我尝试从此列表中获取项目并将其更改为其他项目,它也会更改列表中的原始项目(它将用作引用而不是新实例)。

Dim newitem2 As New entry
newitem2 = MyList.Item(0)
newitem2.val = "something else"

现在MyList.item(0).val包含“其他内容”,但我只希望newitem2包含给定字段的新值,并保留列表中对象的其他值。

如果没有逐个重新分配所有字段,有没有办法做到这一点?

1 个答案:

答案 0 :(得分:2)

如果将entry定义为引用类型(Class),那么您唯一的选择是显式创建一个与原始值具有相同值的新实例。例如:

Public Partial Class Entry
    Public Function Clone() As Entry
        Return New Entry() With { .val = Me.val, … }
    End Function
End Class

(.NET Framework类库从一开始就为这个目的定义了一个类型ICloneable。这种类型从来没有真正流行起来。)

请注意,您可能必须以递归方式执行此操作,也就是说,如果您的类包含具有引用类型的字段,则您还必须克隆存储在这些字段中的对象。

然后,而不是这样做:

Dim newitem2 As New entry  ' (Btw.: `New` is superfluous here, since you are
newitem2 = MyList.Item(0)  '         going to throw away the created instance here.)

这样做:

Dim newitem2 As Entry = MyList.Item(0).Clone()

另一种方法是使用值类型(即将项目类型声明为Structure)。传递时会自动复制值类型。但是,有很多需要注意的事项,其中包括:

  • 如果您的类型包含许多字段,请不要这样做。 (为什么?许多字段通常意味着类型将在内存中占用更多字节,这使得如果对象变得太大,频繁复制会非常昂贵。)

  • 值类型应该是不可变类型。 (为什么?请参阅例如Why are mutable structs evil?

这些只是两条准则。您可以在此处找到有关此主题的更多信息: