实例集合的意外行为

Clo*_*ock 0 .net c# collections instance

例如,我有以下类:

class Person
{
    public List<int> Grades{ get; set; }

    public Person(List<int> grades)
    {
        this.Grades = grades;
    }
}
Run Code Online (Sandbox Code Playgroud)

而且我在主方法中使用这个类,比如:

    static   void Main(string[] args)
    {
        List<int> grades = new List<int> { 1, 2, 3, 4, 5 };
        Person person = new Person(grades);

        for (int i = 0; i < 5; i++)
        {
            if (i % 2 == 0)
            {
                grades[i] = 0;
            }
            else
            {
                grades[i] = -1;
            }
        }

        foreach(var grade in person.Grades)
        {
            Console.Write(grade + " ");
        }

        Console.ReadKey();
    }
Run Code Online (Sandbox Code Playgroud)

运行此代码后,我希望在控制台上:1 2 3 4 5输出结果.Insteead我有这个输出结果:0 -1 0 -1 0

我希望集合"保存"到Person实例中以保持它的初始化方式.我应该怎么做才能保持这个集合不被修改为Person实例,这样即使我在main方法中修改了grade集合,我也会得到"1 2 3 4 5"输出结果.

有人可以解释一下,为什么会这样?

Jon*_*eet 5

我希望集合"保存"到Person实例中以保持它的初始化方式.

是时候重新审视你对C#中引用类型如何工作的期望然后:)我有一篇你可能觉得有用的文章 ......

我应该怎么做才能保持这个集合不被修改为Person实例,这样即使我在main方法中修改了grade集合,我也会得到"1 2 3 4 5"输出结果.

您可以在构造函数中复制集合:

public Person(List<int> grades)
{
    this.Grades = new List<int>(grades);
}
Run Code Online (Sandbox Code Playgroud)

现在可以了List<int>- 如果你有一个可变类型的列表,你可能也希望克隆每个元素.这种事情是为什么不可变类型很好 - 它更容易推理它们的行为,因为没有什么可以搞乱实例,所以你可以保留引用...