【问题标题】:Why does copy of the List still change properties in the original List using C#为什么列表的副本仍然使用 C# 更改原始列表中的属性
【发布时间】:2013-03-02 17:36:29
【问题描述】:

假设我有这门课

public class Employee
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool isActive { get; set; }
}

并像这样使用它:

    List<Employee> Employees = new List<Employee>();
    Employees.Add(new Employee { FirstName = "firstname", LastName = "lastname", isActive = true });
    List<Employee> EmployeesCopy = new List<Employee>(Employees);
    EmployeesCopy[0].isActive = false;

为什么EmployeesCopyisActive 属性的更改也会修改原始列表中的属性?

【问题讨论】:

  • 因为Employee是一个引用类型(类)。
  • 是时候回到书本上,这样您就可以清楚地了解引用类型和值类型之间的区别了。这个 sh*t 真的很重要。确保你得到它。
  • 这可能会帮助你codeproject.com/Articles/76153/…
  • 是的,不是和员工副本,而是包含同一员工的另一个列表。
  • 这是一个问得很好(但重复)的问题。它不值得被否决。 +1

标签: c# .net properties deep-copy shallow-copy


【解决方案1】:

因为新列表仍然包含对相同员工对象的引用。您可以通过执行以下操作在新列表中创建新列表:

    List<Employee> Employees = new List<Employee>();
    Employees.Add(new Employee { FirstName = "firstname", LastName = "lastname", isActive = true });
    List<Employee> EmployeesCopy = Employees.Select(x => new Employee(x)).ToList();

    public class Employee
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public bool isActive { get; set; }

        public Employee()
        { }

        public Employee(Employee e)
        {
            FirstName = e.FirstName;
            LastName = e.LastName;
            isActive = e.isActive;
        }
    }

【讨论】:

  • 如果Employee实现IClonable会更好。
  • 嗯,我认为在这个级别,复制构造函数就可以了。
【解决方案2】:

为什么EmployeesCopy的isActive属性的变化也会修改 原名单?|

因为两个列表都指向 Employee 对象的同一个实例。您还需要 deep copy 您的 Employee 对象。

【讨论】:

    【解决方案3】:

    因为使用new List&lt;Employee&gt;(Employees); 会为您提供 List 的新实例,而不是列表中包含的对象。您还应该考虑克隆列表中包含的对象,使用二进制序列化来序列化对象图。

    【讨论】:

      【解决方案4】:

      您创建的副本只是列表的副本。不是对象的副本。换句话说,Employees[0] == EmployeesCopy[0]

      【讨论】:

        【解决方案5】:

        您正在做浅拷贝,而不是深拷贝。这意味着新列表包含与原始列表相同的对象。

        要进行深层复制,您需要遍历原始列表并为新列表创建新的 Employee 对象,如下所示。

        private List<Employee> CloneEmployees(List<Employee> original)
        {
            var newList = new List<Employee>();
            foreach (var employee in original)
            {
                newList.Add(new Employee 
                    { 
                        FirstName = employee.FirstName, 
                        LastName = employee.LastName, 
                        isActive = employee.isActive 
                    });
            }
            return newList;
        }
        

        【讨论】:

          【解决方案6】:

          副本是一个新的List 对象,但它包含对原始列表中同一组Employee 对象的引用。如果您希望两个列表中的Employee 对象是独立的,那么您必须单独复制它们并将副本放入新列表中。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-09-30
            • 2019-03-27
            • 1970-01-01
            相关资源
            最近更新 更多