Vb.net 从列表中获取项作为新副本(不是作为对原始项的引用)

Vb.net 从列表中获取项作为新副本(不是作为对原始项的引用),vb.net,list,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) 现在,如果我尝试从这个列表中获取一个项目并将

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

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)
现在,如果我尝试从这个列表中获取一个项目并将其更改为其他项目,它也会更改列表中的原始项目(它用作引用而不是新实例)

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


有没有一种方法可以在不逐个重新分配所有字段的情况下执行此操作?

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

Public Partial Class Entry
    Public Function Clone() As Entry
        Return New Entry() With { .val = Me.val, … }
    End Function
End Class
(从早期开始,.NET Framework类库就定义了一个类型,正是出于这个目的。由于某些原因,该类型从未真正流行起来。)

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

然后,不要这样做:

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()

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

  • 如果您的类型包含多个字段,请不要执行此操作。(为什么?许多字段通常意味着该类型将在内存中占用更多字节,如果对象变得太大,则频繁复制将非常昂贵。)

  • 值类型应该是不可变的类型。(为什么?参见示例)

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


感谢您的详尽回答。很多有用的信息。现在我正在考虑使用类似于
IClonable
的东西,但我也会阅读
Struct
Dim newitem2 As Entry = MyList.Item(0).Clone()