【问题标题】:Copy list of items to another list将项目列表复制到另一个列表
【发布时间】:2015-10-16 09:45:31
【问题描述】:

我正在尝试将项目列表从 list1 复制到另一个列表 list2。我能够做到这一点。但是我不希望 list2 中所做的更改反映在 list1 中。

class Program
{
    static void Main(string[] args)
    {
        List<MyClass> list1 = new List<MyClass>();
        list1.Add(new MyClass(){ID = 1, Name = "name1"});
        list1.Add(new MyClass(){ID = 2, Name = "name2"});
        list1.Add(new MyClass(){ID = 3, Name = "name3"});

        //Copy items from list1 to list2
        List<MyClass> list2 = new List<MyClass>(list1);

        list1.ForEach(x => Console.WriteLine(x.Name));   //It shows the name as added

        //Empty items in list2
        list2.ForEach(x => x.Name = string.Empty);

        //Print items in list1
        list1.ForEach(x => Console.WriteLine(x.Name));   //It shows the name is empty
        Console.ReadKey();
    }
}

class MyClass
{
    private int id;

    public int ID
    {
        get { return id; }
        set { id = value; }
    }

    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

我希望应该有一个简单的方法。

【问题讨论】:

  • 你需要的只是一个深拷贝。尝试自己做。

标签: c# ienumerable


【解决方案1】:

由于这是一个引用类型,因此您将全部更改。您需要创建该实例的副本

public class MyClass 
{
    private int id;

    public int ID
    {
        get { return id; }
        set { id = value; }
    }

    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public MyClass Copy()
    { 
        return new MyClass
        {
            ID = this.ID,
            Name = this.Name
        };
    }
}

现在您可以通过这种方式创建第二个列表:

List<MyClass> list2 = new List<MyClass>(list1.Select(x => x.Copy()));

当然你不需要那个方法。您也可以在 LINQ 查询中即时执行此操作:

List<MyClass> list2 = new List<MyClass>(list1.Select(x => new MyClass { ID = x.ID, Name = x.Name }));

另一个类似的方法是copy-constructor。复制构造函数用于通过提供另一个相同类型的实例来初始化一个实例:

public class MyClass
{
    private int id;

    public MyClass(MyClass instance)
    {
        this.id = instance.ID;
        this.name = instance.Name;
    }

    public int ID
    {
        get { return id; }
        set { id = value; }
    }

    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

现在您可以用这种方式在列表中填充副本:

List<MyClass> list2 = new List<MyClass>(list1.Select(x => new MyClass(x)));

List.ConvertAll:

List<MyClass> list2 = list1.ConvertAll(x => new MyClass(x));

【讨论】:

  • 谢谢@Tim。 .它对我有用。我希望这是复制构造函数。不确定:)
  • @Gopichandar: 什么是复制构造函数?不过,我很高兴它对您有所帮助。
  • @Gopichandar:它不是一个复制构造器,因为它不是一个构造器,而是一个普通的实例方法。它类似于工厂方法。复制构造函数用于通过提供另一个相同类型的实例来初始化一个实例。你也可以这样做。这是一种相似但不同的方法。
  • @Gopichandar:我已经编辑了我的答案以添加您的复制结构;)
  • 哦。感谢那。 . :)
【解决方案2】:

如果您也想在其他地方使用此功能,我想最好的方法是为IList 创建一个扩展方法,如下所示:

static class Extensions
{
   public static IList<T> Clone<T>(this IList<T> sourceList) 
      where T: ICloneable
   {
       return sourceList.Select(item => (T)item.Clone()).ToList();
   }
}

要使用它,您应该更改您的课程并使其成为ICloneable

class MyList : ICloneable
{
    public MyList(int idParam, string nameParam)
    {
        ID = idParam;
        Name = nameParam;
    }
    public object Clone()
    {
        return new MyList(ID, Name);
    }

    private int id;
    public int ID
    {
        get { return id; }
        set { id = value; }
    }

    private string name;
    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}
【解决方案3】:

如果您的元素是引用类型并且类型实现 ICloneable 接口,您可以执行以下操作:

list1.ForEach((item) =>
{
    list2.Add((ICloneable)item.Clone());
});

如果您的元素类型没有实现ICloneable,您可以创建“复制”构造函数并执行以下操作:

list1.ForEach((item)=>
    {
        list2.Add(new MyList(item.ID, item.Name));
    });

【讨论】:

  • IClonable 合约没有指定执行克隆的类型,不同的类有不同的实现。消费者不能依赖ICloneable 让他们知道对象是否被深度克隆。出于这个原因,应该避免它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 2010-11-20
  • 2022-11-12
  • 1970-01-01
相关资源
最近更新 更多