列表初始化与其他列表。是否会复制或引用对象?

时间:2018-03-19 05:34:21

标签: c# collections

您好我有一个Person类列表如下

public class person
{
    public int age;
    public string name;
}

我正在尝试执行以下操作。

static void Main(string[] args)
{
    List<person> person1 = new List<person>();
    person1.Add(new person { age = 10, name = "P1" });
    person1.Add(new person { age = 11, name = "Q1" });
    person1.Add(new person { age = 12, name = "R1" });

    List<person> person2 = new List<person>(person1);
    person2[0].name = "P2";
    Console.WriteLine("---------Person1---------");

    foreach (person P in person1)
    {
        Console.WriteLine("Age=" + P.age);
        Console.WriteLine("Name=" + P.name);
    }
    Console.WriteLine("---------Person2---------");
    foreach (person P in person2)
    {
        Console.WriteLine("Age=" + P.age);
        Console.WriteLine("Name=" + P.name);
    }
}

输出是两个列表中第一个对象的值更改为P2,而我希望仅在person2列表中更改它。我以为列表项会被复制到person2列表中。 MSDN here表示将元素复制到新列表中,这在上述情况下不会发生。我在这里错过了什么?

3 个答案:

答案 0 :(得分:1)

你在这里犯的错误是参考变量。列表中包含对person类型对象的引用。复制列表时,它只复制对这些对象的引用,因此每个列表都包含对完全相同对象集的引用。

有关我正在讨论的更深入的示例,请考虑以下代码:

person me = new person { age = 20, name = "Lauraducky" };
person you = me;
you.name = "Programmerzzz";
Console.WriteLine(me.name); // Outputs Programmerzzz

这基本上就是你在你的例子中所做的。 me变量不会被复制,对它的引用只会被传递给you变量。然后更改该参考位置处的对象。这里的关键是两个变量都指向同一个位置。

如果要制作列表的深层副本,则必须手动执行此操作。例如:

List<person> person2 = new List<person>();
foreach (person p in person1) {
    person2.Add(new person { age = p.age, name = p.name });
}

有关参考类型的更多信息,请参阅this excellent explanation

答案 1 :(得分:0)

类是按引用复制的,struct是按值复制的。

因此,您更改了人员的价值,您将链接到原始参考。

public Struct person
{
    public int age;
    public string name;
}

如果您使用struct,请再试一次,您会看到不同的

答案 2 :(得分:0)

您通过引用而不是按值复制。首先要做的是修好你的课程。所以你可以创造“人”。使用构造函数的对象。下面的代码创建了一个新对象,而不是复制前一个列表的引用。

public static void Main()
{

    Console.WriteLine("Program Started!");

    List<person> person1 = new List<person>();
    person1.Add(new person(10, "P1" ));
    person1.Add(new person( 11, "Q1" ));
    person1.Add(new person(12,  "R1" ));

    List<person> person2 = new List<person>();
    foreach(person p in person1)
    {
        person2.Add(new person(p)); //WE COPY BY VALUE. BY ALLOCATING SPACE FOR A NEW OBJECT.
    }

    person2[0].name = "P2";
    Console.WriteLine("---------Person1---------");

    foreach (person P in person1)
    {
        Console.WriteLine("Age=" + P.age);
        Console.WriteLine("Name=" + P.name);
    }
    Console.WriteLine("---------Person2---------");
    foreach (person P in person2)
    {
        Console.WriteLine("Age=" + P.age);
        Console.WriteLine("Name=" + P.name);
    }

    Console.WriteLine("Program Ended!");
    Console.ReadKey();
}

public class person
{
    public int age;
    public string name;

    public person(person p) {
        this.age = p.age;
        this.name = p.name;
    }

    public person(int _age, string _name)
    {
        this.age = _age;
        this.name = _name;
    }

}