C# 从现有实例创建 IList<T> 的新实例并修改它
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14759349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Creating a new instance of IList<T> from an existing one and modifying it
提问by oonyalo
Given the the code below:
鉴于以下代码:
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();
}
}
The output will be:
输出将是:
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...
Can someone please explain to me:
有人可以向我解释一下:
Why after creating the new lists (list2 and list3) that the actions on those lists affects list1 (and subsequently the two other lists)? and
How I can create a new instance of list1 and modify it without affecting list1?
为什么在创建新列表(列表 2 和列表 3)后,这些列表上的操作会影响列表 1(以及随后的其他两个列表)?和
如何在不影响 list1 的情况下创建 list1 的新实例并对其进行修改?
采纳答案by Immortal Blue
You've effectively got a "shallow copy". That yes, the lists are copied, but they still point to the original items.
你实际上得到了一个“浅拷贝”。是的,列表被复制,但它们仍然指向原始项目。
Think of it like this. A list doesn't actually containthe items it contains, instead it has a reference to it. So, when you copy your list the new list just contains a reference to the original item. What you need is something like this
像这样想。列表实际上并不包含它所包含的项目,而是有一个对它的引用。因此,当您复制列表时,新列表仅包含对原始项目的引用。你需要的是这样的
IList newlist = new List<Item>();
foreach(item anItem in myList)
{
newList.Add(item.ReturnCopy());
}
where return copy looks something like this:
返回副本看起来像这样:
public Item ReturnCopy()
{
Item newItem = new Item();
newItem._id = _id;
newItem._order = _order;
newItem._name = _name;
return newItem
}
That will copy all the data from the item, but leave the original intact. There are loads of patterns and interfaces that can offer better implementations, but I just wanted to give you a flavour of how it works.
这将复制项目中的所有数据,但保留原始数据。有大量的模式和接口可以提供更好的实现,但我只是想让你了解它是如何工作的。
回答by driis
You have 3 lists, but they contain the same 4 elements (ie. references to the same 3 objects in memory). So when you modify order in an item in List1, it also takes effect in the item in List2 - because it is the same object.
您有 3 个列表,但它们包含相同的 4 个元素(即对内存中相同 3 个对象的引用)。所以当你在 List1 中的 item 中修改 order 时,它也会在 List2 中的 item 中生效——因为它是同一个对象。
Neither ToList nor the List constructor makes a deep copy.
ToList 和 List 构造函数都不进行深拷贝。
If you want to copy the objects too, you need to copy them also, to create new references to add to the new lists. In .NET, you would typically implement ICloneable<T>
in order to provide a Clone
method. If you don't feel you need that, you can just create new Item
s and copy their properties.
如果您也想复制对象,则还需要复制它们,以创建新引用以添加到新列表中。在 .NET 中,您通常会实现ICloneable<T>
以提供一种Clone
方法。如果您觉得不需要,您可以创建新的Item
s 并复制它们的属性。
回答by Aniket Inge
static class Extension
{
public static IList<T> Clone<T>(this IList<T> list) where T: ICloneable
{
return list.Select(i => (T)i.Clone()).ToList();
}
}
Now you can use IList<T>.Clone()
to return objects.
现在您可以使用IList<T>.Clone()
返回对象。
回答by Beachwalker
You need to clone the objects within the lists. Otherwise you create new lists and they all point to the same objects.
您需要克隆列表中的对象。否则,您创建新列表,它们都指向相同的对象。
var listToClone = new List<Item>();
var clonedList = listToClone.Select(item => (Item)item.Clone()).ToList();
回答by Servy
You have 3 distinct lists, and so editing those lists (i.e. adding a new item to the list, removing an item, setting a new item at a given position) is a change that won't affect the other variables.
您有 3 个不同的列表,因此编辑这些列表(即向列表中添加新项目、删除项目、在给定位置设置新项目)是一种不会影响其他变量的更改。
However, the item in each of the lists only contains a reference to an actual Item
instance, and all three lists have the same three references. When you change the item that is referenced by that list you are making a change that is "visible" from the other lists.
但是,每个列表中的项目仅包含对实际Item
实例的引用,并且所有三个列表都具有相同的三个引用。当您更改该列表引用的项目时,您所做的更改在其他列表中是“可见的”。
In order to not see this behavior you need to not only create a new list, but ensure that the items in the new list(s) are brand new references to new objects that happen to contain the same values. In the general case, this isn't a trivial task, nor is it often desirable.
为了不看到这种行为,您不仅需要创建一个新列表,还要确保新列表中的项目是对碰巧包含相同值的新对象的全新引用。在一般情况下,这不是一项微不足道的任务,通常也不是可取的。