我有apples
的列表,我找到了红色的列表:
var redApples = apples.Where(a => a.colour == "red");
redApples
此处为IEnumerable
,因此如果我将其转换为列表:
var redApplesList = redApples.ToList();
这为我提供了新对象的列表。所以,如果我修改这些对象:
redApplesList.ForEach(a => a.color = "blue");
我不希望原始apples
列表中的项目根本改变颜色。但事实并非如此,我原始列表中的"red"
的苹果现在是"blue"
。
这里有什么误解?
我的印象ToList()
创建了一个独立于现有列表的全新项目列表,但这表明原始列表中的指针已更新为指向新创建的对象?这是发生在幕后的事情吗?
答案 0 :(得分:6)
它为您提供了一个新列表,但该列表包含与原始列表相同的对象的引用(apple
是一个类=引用类型)。它们不会被复制,因此当您通过第二个列表引用其中一个并更改它时,它就是更新的原始项目。
如果您要复制项目,请查看deep copy,一种方法是使用ICloneable
(另一种方式,因为Kyle评论使用的是copy constructor)
如果你实现了这样的课程:
public class Apple : ICloneable
{
public string Color { get; set; }
public object Clone()
{
return new Apple { Color = Color };
}
}
然后检查一下:
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
如果没有调用.Clone
,就会得到相同的引用。使用.Clone
,您可以获得新对象。因此,当您更改Color
时,它不会影响原始
在阅读了更多内容(Copy constructor versus Clone())后,我建议改为使用复制构造函数:
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();
答案 1 :(得分:3)
它不会创建新对象的列表。它会创建现有对象的新列表 。