【问题标题】:Clone a List(Of Class)克隆一个列表(类)
【发布时间】:2013-01-06 04:59:22
【问题描述】:

我已经阅读了一些内容,但似乎无法理解在我的 VB2010 项目中克隆 List(of class) 的最佳方法是什么。我有三个像这样相关的类

Public Class City
    'here are many fields of type string and integer
    Public Roads As New List(Of Road)
End Class
Public Class Road
    'here are many fields of type string and integer
    Public Hazards As New List(Of Hazard)
End Class
Public Class Hazard
    Implements ICloneable

    'here are many fields of type string and integer and double
    Public Function Clone() As Object Implements System.ICloneable.Clone
        Return Me.MemberwiseClone
    End Function
End Class

假设我有一个正在开发的城市,在某些情况下,我想创建一条道路及其危险,然后添加另一条道路,但使用之前的道路危险作为起点,然后调整字段。

Dim rd As New Road
'add road fields

dim hz1 as New Hazard
'add hazard fields
dim hz2 as New Hazard
'add hazard fields

'add the hazard objects to the road
rd.Hazards.Add(hz1)
rd.Hazards.Add(hz2)

'add the road to the city
myCity.Roads.Add(rd)


'here I want to start a new road based on the old road
Dim rdNew As New Road

'copy or clone the hazards from old road
rdNew.Hazards = rd.Hazards '<============

'over-write some of the hazard fields
rdNew.Hazards(0).Description = "temp"

所以我知道复制一个类将复制指针而不是内容。我在危险类中使用了 ICloneable 接口,但不能说我使用正确。 Hazards 变量是 Hazard 类别的列表。我将如何克隆该类?

【问题讨论】:

  • 您需要只复制列表,还是还需要复制列表中的每个对象?
  • 您似乎想要一个深度克隆
  • 我想要一份完整的副本。换句话说,Hazards 的所有成员都会被复制到新的道路上。 Hazards 包含字符串、双精度数、整数和一个枚举。我认为克隆就是它的名称,因此我不只是指向原始危害类。

标签: vb.net list class clone icloneable


【解决方案1】:

实现IClonable 并不意味着它取代了常规赋值,它仍然只是复制引用。而且您甚至没有复制项目,而是在复制列表,这意味着您仍然只有一个列表,但是对它的两个引用。

要使用Clone 方法,您必须为列表中的每个项目调用它:

rdNew.Hazards = rd.Hazards.Select(Function(x) x.Clone()).Cast(Of Hazard).ToList()

【讨论】:

  • 好的,让我试试。我看到的所有示例代码都与变量而不是列表有关,这就是我进行查询的原因。
  • 在我的测试中这似乎有效。如果我发现任何问题,我会回复。
【解决方案2】:
Imports System.IO
Imports System.Xml.Serialization        

 Public Function CopyList(Of T)(oldList As List(Of T)) As List(Of T)

            'Serialize
            Dim xmlString As String = ""
            Dim string_writer As New StringWriter
            Dim xml_serializer As New XmlSerializer(GetType(List(Of T)))
            xml_serializer.Serialize(string_writer, oldList)
            xmlString = string_writer.ToString()

            'Deserialize
            Dim string_reader As New StringReader(xmlString)
            Dim newList As List(Of T)
            newList = DirectCast(xml_serializer.Deserialize(string_reader), List(Of T))
            string_reader.Close()

            Return newList
        End Function

【讨论】:

    【解决方案3】:

    我知道这是旧的。

    rdNew.Hazards = rd.Hazards.ToList()
    

    即使它已经是一个列表,ToList 也会基于它创建一个新列表。

    在 VB 2019 中,这将创建一个浅拷贝,但这在某些情况下很有用。这意味着该列表是新的,但 rd.HazardsrdNew.Hazards 的元素指向同一事物。

    如果您编辑任何特定的危险,更改将在两者中看到。

    如果您将危害添加到一个列表,则另一个列表将没有它。

    如果您从一个列表中删除危害,则另一个列表仍将保留它。

    如果 Hazard 是原始类型(如字符串或整数),则编辑项目不会反映在其他列表中。

    【讨论】:

      猜你喜欢
      • 2017-04-11
      • 1970-01-01
      • 2011-12-26
      • 2017-03-26
      • 2010-10-05
      • 1970-01-01
      • 1970-01-01
      • 2021-05-21
      • 1970-01-01
      相关资源
      最近更新 更多