C# ToList() 方法是否真的制作了卷影副本?

问题描述

根据以下链接,在调用 ToList() 方法时会进行卷影复制。

https://forums.asp.net/t/1638787.aspx?Does+ToList+create+a+shallow+or+deep+copy+of+an+existing+List+collection+

我测试了一些案例,但我发现了一些奇怪的东西。

  1. 案例 - 自定义类 => 结果与上述结论一致。如果我更改了一个列表中对象的属性,而另一个列表也更改了。

  2. 大小写 - 字符串 => 结果与上述结论相矛盾。我已经更改了一个列表中的字符串,但另一个列表中的值仍然与以前相同。

在我看来,Custom Class 和 String 都是对象,有什么区别? 任何人都可以建议吗?非常感谢!

var originalList1 = new List<Person> { new Person { Name = "Apple" },new Person { Name = "Banana" } };
var copyList1 = originalList1.ToList();

originalList1[0].Name = "Orange";

Console.WriteLine(originalList1[0].Name);   // Orange
Console.WriteLine(copyList1[0].Name);       // Orange    


var originalList2 = new List<string> { "Apple","Banana" };
var copyList2 = originalList2.ToList();

originalList2[0] = "Orange";
Console.WriteLine(originalList2[0]);        // Orange
Console.WriteLine(copyList2[0]);            // Apple  --- Why?

解决方法

你不能“改变”一个字符串——字符串是不可变的。您正在用新字符串替换原始列表中位置 0 处的字符串。这不会影响另一个列表的索引 0 处的字符串。

List<Person> 情况下,列表包含对对象的引用。复制列表时 - 引用 被复制,但它们指向相同的对象,因此替换这些对象之一的属性会反映在两个列表中。