【问题标题】:In C# How do I copy a list to another list in such a way that on modifying the copied list the original list is not modified在 C# 中,如何将一个列表复制到另一个列表,这样在修改复制的列表时原始列表不会被修改
【发布时间】:2016-06-24 16:23:40
【问题描述】:

我正在尝试使用 AddRange 或其他方式将一个列表复制到另一个列表,但似乎没有任何工作正常。无论我尝试何种方式,我都会修改复制的列表,它也会修改原始列表。如果我使用 foreach 循环进行复制,这是唯一可行的方法。

    static void Main(string[] args)
    {
        var test = new List<Employee>{ new Employee { ID = "101", Name ="ABC1"}, new Employee{ID = "102", Name = "ABC2"}, new Employee{ ID = "103", Name = "ABC3"}};

        var tets2 = new List<Employee>(test);

        tets2[0].ID = "1-73";
        TestMethod(test.ToList());
    }

    private static void TestMethod(List<Employee> test)
    {
        var test1 = new List<Employee>(test);

        test1.AddRange(test);

        //This is the only one that work
        foreach(var item in test)
        {
            var x = new Employee { ID = item.ID, Name = item.Name };
            test1.Add(x);
        }

        test1[0].ID = "104";
    }

没有更短的方法吗?

【问题讨论】:

  • 我相信你可以使用 LINQ:originalList.ForEach(x =&gt; CopiedList.Add(new CopiedListObject { prop = x.prop, prop2 = x.prop2 })

标签: c# list copy


【解决方案1】:

它不是在修改列表 - 它是在修改列表中的项目。 您可以有两个或多个列表 - 每个列表都是 List&lt;Employee&gt; - 如果您将项目复制到另一个列表或数组,则两个列表中的项目是相同的项目。

var x = new Employee { ID = "xyz", Name = "Bob" };
var list = new List<Employee>();
list.Add(x);
var array = new Employee[]{x};
var y = x;
y.ID = "abc";

在此示例中,Employee 的实例只有一个,但该Employee 有四个引用

  • x 是一个参考
  • list[0] 是另一个
  • array[0]
  • y

但是,您指的是那个实例,包括list[0].ID = "new id",它都是Employee 的同一个实例。

要创建副本,您可以执行以下操作 - 这是一个冗长的示例,不一定是您想要实际实现的方式:

var newList = new List<Employee>();
foreach(var employee in sourceList) //the list you want to copy from
{
    newList.Add(new Employee{ID=employee.ID, Name=employee.Name});
}

添加到newList 的项目与sourceList 中的对象不同。它们是具有相同属性的新对象。

如果您预见到需要经常执行此操作,那么您可以让 Employee 实现 ICloneable

public class Employee : ICloneable
{
    public string ID {get;set;}
    public string Name {get;set;}
    public object Clone()
    {
        return new Employee{ID=ID, Name=Name};
    }
}

或者,因为属性只是值类型,您可以这样做,将源对象中的属性复制到新对象中。

public class Employee : ICloneable
{
    public string ID {get;set;}
    public string Name {get;set;}
    public object Clone()
    {
        return this.MemberwiseClone();
    }
}

然后要创建一个新列表,您可以创建一个扩展方法:

public static class EmployeeExtensions
{
    public static List<Employee> ToClonedList(this IEnumerable<Employee> source)
    {
        return source.Select(employee => employee.Clone() as Employee).ToList();
    }
}

然后,您可以从任何IEnumerable 员工集创建一个克隆列表,如下所示:

var myClonedList = oldList.ToClonedList();

(要拆分头发,您不必实现ICloneable。您可以只编写一个复制对象的方法。ICloneable 只是一个约定,让其他人知道他们可以调用.Clone() 并创建一个克隆对象。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2016-05-21
    • 2016-02-28
    • 2019-03-27
    • 1970-01-01
    • 2011-09-30
    相关资源
    最近更新 更多