鉴于以下代码:
public class Item
{
private int _id;
private int _order;
private string _name;
public int Id
{
get { return _id; }
set { _id = value; }
}
public int Order
{
get { return _order; }
set { _order = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public static IList<Item> InitList1()
{
var list = new List<Item>
{
new Item { Id = 1, Order = 1, Name = "Alpha" },
new Item { Id = 2, Order = 2, Name = "Bravo" },
new Item { Id = 3, Order = 3, Name = "Charlie" },
new Item { Id = 4, Order = 4, Name = "Delta" }
};
return list;
}
}
class Program
{
static void Main(string[] args)
{
// Initialize the lists
IList<Item> list1 = Item.InitList1();
IList<Item> list2 = list1.ToList();
IList<Item> list3 = new List<Item>(list1);
// Modify list2
foreach (Item item in list2)
item.Order++;
// Modify list3
foreach (Item item in list3)
item.Order++;
// Output the lists
Console.WriteLine(string.Format("\nList1\n====================="));
foreach (Item item in list1)
Console.WriteLine(string.Format("Item - id: {0} order: {1} name: {2}", item.Id, item.Order, item.Name));
Console.WriteLine(string.Format("\nList2\n====================="));
foreach (Item item in list2)
Console.WriteLine(string.Format("Item - id: {0} order: {1} name: {2}", item.Id, item.Order, item.Name));
Console.WriteLine(string.Format("\nList3\n====================="));
foreach (Item item in list3)
Console.WriteLine(string.Format("Item - id: {0} order: {1} name: {2}", item.Id, item.Order, item.Name));
Console.Write("\nAny key to exit...");
Console.ReadKey();
}
}
输出将是:
List1
=====================
Item - id: 1 order: 3 name: Alpha
Item - id: 2 order: 4 name: Bravo
Item - id: 3 order: 5 name: Charlie
Item - id: 4 order: 6 name: Delta
List2
=====================
Item - id: 1 order: 3 name: Alpha
Item - id: 2 order: 4 name: Bravo
Item - id: 3 order: 5 name: Charlie
Item - id: 4 order: 6 name: Delta
List3
=====================
Item - id: 1 order: 3 name: Alpha
Item - id: 2 order: 4 name: Bravo
Item - id: 3 order: 5 name: Charlie
Item - id: 4 order: 6 name: Delta
Any key to exit...
有人可以向我解释一下:
为什么在创建新列表(list2和list3)后,这些列表上的操作会影响list1(以及随后的其他两个列表)?以及
如何创建list1的新实例并修改它而不影响list1?
答案 0 :(得分:10)
你实际上得到了一份“浅层副本”。是的,列表被复制,但它们仍然指向原始项目。
这样想。列表实际上不包含它包含的项目,而是具有对它的引用。因此,当您复制列表时,新列表只包含对原始项的引用。你需要的是这样的东西
IList newlist = new List<Item>();
foreach(item anItem in myList)
{
newList.Add(item.ReturnCopy());
}
返回副本看起来像这样:
public Item ReturnCopy()
{
Item newItem = new Item();
newItem._id = _id;
newItem._order = _order;
newItem._name = _name;
return newItem
}
这将复制项目中的所有数据,但保留原始数据。有很多模式和接口可以提供更好的实现,但我只想告诉你它是如何工作的。
答案 1 :(得分:4)
您有3个列表,但它们包含相同的4个元素(即对内存中相同3个对象的引用)。因此,当您修改List1中的项目中的顺序时,它也会在List2中的项目中生效 - 因为它是同一个对象。
ToList和List构造函数都没有进行深层复制。
如果您还要复制对象,还需要复制它们,以创建新引用以添加到新列表。在.NET中,您通常会实现ICloneable<T>
以提供Clone
方法。如果您觉得不需要,可以创建新的Item
并复制其属性。
答案 2 :(得分:1)
static class Extension
{
public static IList<T> Clone<T>(this IList<T> list) where T: ICloneable
{
return list.Select(i => (T)i.Clone()).ToList();
}
}
现在您可以使用IList<T>.Clone()
返回对象。
答案 3 :(得分:1)
您有3个不同的列表,因此编辑这些列表(即在列表中添加新项目,删除项目,在给定位置设置新项目)是一个不会影响其他变量的更改。 / p>
但是,每个列表中的项目仅包含对实际Item
实例的引用,并且所有三个列表都具有相同的三个引用。当您更改该列表引用的项目时,您正在进行其他列表中“可见”的更改。
为了不看到此行为,您不仅需要创建新列表,还要确保新列表中的项是对碰巧包含相同值的新对象的全新引用。在一般情况下,这不是一项微不足道的任务,也不是经常需要的。
答案 4 :(得分:0)
您需要克隆列表中的对象。否则,您将创建新列表,并且它们都指向相同的对象。
var listToClone = new List<Item>();
var clonedList = listToClone.Select(item => (Item)item.Clone()).ToList();