You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 20:01:00