【问题标题】:Is there any better deep clone methods for list? [duplicate]列表有更好的深度克隆方法吗? [复制]
【发布时间】:2017-11-03 22:09:55
【问题描述】:

所以我需要一种深度克隆的方法。我希望一张卡片列表与另一张卡片列表相同,但我还想修改其中一个克隆。

我做了一个方法来复制这样的列表:

    public List<Card> Copy(List<Card> cards)
    {
        List<Card> clone = new List<Card>();
        foreach (var card in cards)
        {
            clone.Add(card);
        }
        return clone;
    }

并像这样使用它:

        _cards = new List<Card>();
        _thrownCards = new List<Card>();

        _cards = Copy(_thrownCards);
        _thrownCards.Clear();

我没有 C# 经验,但不知何故,我的直觉告诉我,我的复制方法可以变得更简单。没有其他方法可以深度复制列表吗?我尝试使用MemberWiseClone,但这只是创建了对同一个对象的引用,而不是克隆它(可能我误解了 MemberWiseClone 方法)。

有没有人知道如何简单地克隆一个列表对象?

【问题讨论】:

  • 您可以使用cards.ToList() 克隆列表,但如果Card 是引用类型,您还需要克隆每个列表元素以获得深层副本。
  • 您的方法不是深度克隆,因为所有Card 实例都没有被克隆,而只是复制到另一个列表(假设它们不是结构)。
  • 我只想指出,由于您的 Copy 函数创建并返回 new List&lt;Card&gt;(),因此您实际上不需要先初始化 _cards。您可以像这样使用您的函数:_thrownCards = new List&lt;Card&gt;(); ...; _cards = Copy(_thrownCards); _thrownCards.Clear(); 另外,您在 Copy 函数中实际执行的操作是浅层克隆。这是一个Stackoverflow question,关于两者之间的区别。

标签: c# deep-copy


【解决方案1】:

这不是真正的深拷贝,因为 Card 实例仍然相同,只是列表不同。你可以更简单:

List<Card> cloneList = cards.ToList();

您还需要“复制”Card 实例的所有属性:

public List<Card> Copy(List<Card> cards)
{
    List<Card> cloneList = new List<Card>();
    foreach (var card in cards)
    {
        Card clone = new Card();
        clone.Property1 = card.Property1;
        // ... other properties
        cloneList.Add(clone);
    }
    return cloneList;
}

您还可以提供一个工厂方法来创建给定Card 实例的克隆:

public class Card
{
    // ...

    public Card GetDeepCopy()
    {
        Card deepCopy = new Card(); 
        deepCopy.Property1 = this.Property1;
        // ...
        return deepCopy;
    }
}

然后您将这个逻辑封装在一个地方,您甚至可以访问private 成员(字段、属性、构造函数)。将上面Copy方法中的行改为:

cloneList.Add(card.GetDeepCopy()); 

【讨论】:

  • 您是否建议将复制方法放在Card 本身上? cloneList.Add(card.DeepCopy())
  • @TimSchmelter 抱歉,出现错误并误解了我自己的结构。这很好用,所以我将其标记为解决方案!
【解决方案2】:

要拥有深拷贝,你需要有这样的东西:

public List<Card> Copy(List<Card> cards)
{
    List<Card> clone = new List<Card>();
    foreach (var card in cards)
    {
        clone.Add(new Card 
        {
          property1 = card.property1;
          property2 = card.property2; // and so on
        });
    }
    return clone;
}

当然,如果property1property2 也是引用类型的对象,那你就得更深入了。

【讨论】:

    【解决方案3】:

    怎么样

    List<Card> _cards = _thrownCards.ConvertAll(Card => new Card(<card parameters here>));
    

    【讨论】:

      【解决方案4】:

      不同于我们只复制引用时的复制

       public List<Card> Copy(List<Card> cards) {
         return cards.ToList();
       }
      

      如果是 deep 副本,我们必须克隆 每个项目

       public List<Card> Copy(List<Card> cards) {
         return cards
           .Select(card => new Card() {
              //TODO: put the right assignment here  
              Property1 = card.Property1,
              ...
              PropertyN = card.PropertyN,
           }) 
           .ToList();
       }
      

      【讨论】:

        猜你喜欢
        • 2011-12-22
        • 2010-11-18
        • 2013-10-11
        • 1970-01-01
        • 2019-03-25
        • 2010-10-25
        • 2015-01-08
        • 2013-04-04
        相关资源
        最近更新 更多