如何从列表中获取项目作为新的副本/实例,以便我可以在以后使用和更改它而不更改列表中的原始对象?
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
包含给定字段的新值,并保留列表中对象的其他值。
如果没有逐个重新分配所有字段,有没有办法做到这一点?
答案 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?)
这些只是两条准则。您可以在此处找到有关此主题的更多信息: