C#修改类内List元素值时同步变更问题求助
问题:员工任务列表修改同步的问题
我暂停编码已有一段时间,可能问题看起来有些基础,但仍需求助。我定义了如下Employee类和task类,随后创建了两个Employee对象并添加到员工列表中,尝试修改其中一个员工的task的duration值时,发现两个员工的该值都会被修改。我希望基于同一个基础任务列表创建员工,但每个员工的任务列表能独立修改,请问问题出在哪里?
定义的类代码
Employee类
public class Employee { public string Name { get; set; } public List<task> tasks {get; set;} public Employee(string name, List<task> ListTasks) { Name = name; tasks = new List<task>(); //tasks=ListTasks; tasks.AddRange(ListTasks); } }
task类
public class task { public string Titel { get; set; } public int duration { get; set; } = 0; public int maxDuration { get; set; } }
Main方法代码
private static void Main(string[] args) { var taskList = new List<task> { new task { Titel = "Bumm", maxDuration = 4 }, new task { Titel = "Kaban", maxDuration = 8 } }; Employee bla1 = new Employee("werner", taskList); Employee bla2 = new Employee("ecki", taskList); var empListe = new List<Employee> { bla1, bla2 }; // bla2.tasks[1].Dauer = 2; empListe[1].tasks[1].duration = 2; foreach (var name in empListe) { Console.WriteLine(name.Name); foreach (var line in name.tasks) { Console.WriteLine("{0}: {1}/{2}",line.Titel, line.duration, line.maxDuration); } } }
问题原因与解决方案
问题核心原因
你遇到的问题是引用类型的浅拷贝导致的:
task是引用类型(class),即使你给每个Employee新建了List<task>集合,通过AddRange添加的只是原始task对象的引用,而非新实例。- 两个员工的任务列表是不同的集合,但集合里的每个task都指向同一个内存对象,所以修改其中一个员工的task属性,另一个员工的对应task也会同步变化。
解决方案
1. 手动复制task属性创建新实例
修改Employee构造函数,逐个复制原始task的属性,为每个员工创建独立的task实例:
public Employee(string name, List<task> ListTasks) { Name = name; tasks = new List<task>(); // 遍历原始任务列表,创建新的task实例并添加 foreach (var originalTask in ListTasks) { tasks.Add(new task { Titel = originalTask.Titel, duration = originalTask.duration, maxDuration = originalTask.maxDuration }); } }
2. 将task改为值类型(struct)
如果task的业务逻辑适合作为值类型,可以把class改成struct。值类型在赋值或添加到列表时会自动创建副本,每个员工的task都是独立实例:
public struct task { public string Titel { get; set; } public int duration { get; set; } = 0; public int maxDuration { get; set; } }
注意:struct是值类型,若需要修改属性,需确保使用方式符合值类型特性(比如不可变性设计更安全)。
3. 实现ICloneable接口进行克隆
给task类实现ICloneable接口,提供克隆方法来创建实例副本:
public class task : ICloneable { public string Titel { get; set; } public int duration { get; set; } = 0; public int maxDuration { get; set; } public object Clone() { return new task { Titel = this.Titel, duration = this.duration, maxDuration = this.maxDuration }; } }
然后在Employee构造函数中调用克隆方法生成新列表:
public Employee(string name, List<task> ListTasks) { Name = name; tasks = ListTasks.Select(t => (task)t.Clone()).ToList(); }
内容的提问来源于stack exchange,提问作者Synav
相关产品推荐
相关产品推荐

