我有一个列表apples,我发现那些是红色的:
var redApples = apples.Where(a => a.colour == "red");
Run Code Online (Sandbox Code Playgroud)
redApples是一个IEnumerable在这里,所以如果我将其转换为列表:
var redApplesList = redApples.ToList();
Run Code Online (Sandbox Code Playgroud)
这给了我一个新对象列表.所以,如果我修改这些对象:
redApplesList.ForEach(a => a.color = "blue");
Run Code Online (Sandbox Code Playgroud)
我不希望原始apples列表中的项目根本改变颜色.但这不是发生的事情,我原来列表中的苹果"red"现在都是"blue".
这里有什么误会?
我在印象中ToList()创建了一个独立于现有列表的全新项目列表,但这表明原始列表中的指针已更新为指向新创建的对象?这是发生在引擎盖下的事情吗?
许多开发人员似乎都倾向于将事物分离成单独的列表(甚至是克隆对象),因为他们从不100%确定他们正在使用什么.了解这一领域将是有益的.
它为您提供了一个新列表,但该列表包含apple与原始列表相同的对象的引用(是类=引用类型).它们不会被复制,因此当您通过第二个列表引用其中一个并进行更改时,它将与更新的原始项目相同.
如果您希望将项目复制到深层复制中,一种方法是使用ICloneable(另一种方式是Kyle评论使用的是复制构造函数)
如果你实现这样的类:
public class Apple : ICloneable
{
public string Color { get; set; }
public object Clone()
{
return new Apple { Color = Color };
}
}
Run Code Online (Sandbox Code Playgroud)
然后检查一下:
List<Apple> apples = new List<Apple>
{
new Apple { Color = "red" },
new Apple { Color = "blue" },
};
var redAppels = apples.Where(a => a.Color == "red").Select(a => (Apple)a.Clone()).ToList();
redAppels[0].Color = "green";
Console.WriteLine($"Original: {apples[0].Color}, new: {redAppels[0].Color}");
// Original red, new: green
Run Code Online (Sandbox Code Playgroud)
没有你的电话,.Clone你得到相同的参考.随着.Clone你得到新的对象.因此,当你改变它们时Color它不会影响原始
在阅读了一下之后(复制构造函数与克隆())我建议去复制构造函数:
public class Apple
{
public Apple() { }
public Apple(Apple apple)
{
Color = apple?.Color;
}
public string Color { get; set; }
}
var redAppels = apples.Where(a => a.Color == "red")
.Select(a => new Apple(a))
.ToList();
Run Code Online (Sandbox Code Playgroud)