Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建IList的新实例<;T>;从一个现有的,并修改它_C#_.net_Ienumerable_Ilist - Fatal编程技术网

C# 创建IList的新实例<;T>;从一个现有的,并修改它

C# 创建IList的新实例<;T>;从一个现有的,并修改它,c#,.net,ienumerable,ilist,C#,.net,Ienumerable,Ilist,鉴于以下代码: 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; }

鉴于以下代码:

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();
    }
}
谁能给我解释一下:

  • 为什么在创建新列表(列表2和列表3)后,这些列表上的操作会影响列表1(以及随后的两个其他列表)?及

  • 如何创建list1的新实例并对其进行修改而不影响list1


  • 您有3个列表,但它们包含相同的4个元素(即对内存中相同3个对象的引用)。因此,当您在列表1中的项目中修改顺序时,它也会在列表2中的项目中生效,因为它是同一个对象

    ToList和List构造函数都不会生成深度副本

    如果也要复制对象,还需要复制它们,以创建要添加到新列表中的新引用。在.NET中,您通常会实现
    ICloneable
    ,以提供
    Clone
    方法。如果您觉得不需要,您可以创建新的
    s并复制它们的属性。

    静态类扩展
    
    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克隆(此IList列表),其中T:ICloneable { 返回列表。选择(i=>(T)i.Clone()).ToList(); } }

    现在,您可以使用IList.Clone()返回对象。

    您需要克隆列表中的对象。否则,您将创建新列表,它们都指向相同的对象

    var listToClone = new List<Item>();
    
    var clonedList = listToClone.Select(item => (Item)item.Clone()).ToList();
    
    var listToClone=new List();
    var clonedList=listToClone.Select(item=>(item)item.Clone()).ToList();
    
    您有3个不同的列表,因此编辑这些列表(即向列表中添加新项目、删除项目、在给定位置设置新项目)是一项不会影响其他变量的更改

    但是,每个列表中的项仅包含对实际
    实例的引用,并且所有三个列表都具有相同的三个引用。当您更改该列表所引用的项目时,您所做的更改将从其他列表中“可见”

    为了不看到这种行为,您不仅需要创建一个新列表,还需要确保新列表中的项目是对新对象的全新引用,这些对象恰好包含相同的值。在一般情况下,这不是一项琐碎的任务,通常也不可取。

    您实际上得到了一个“浅拷贝”。如果是,列表将被复制,但它们仍然指向原始项目

    这样想吧。列表实际上并不包含它所包含的项,而是有一个对它的引用。因此,复制列表时,新列表只包含对原始项的引用。你需要的是这样的东西

    IList newlist = new List<Item>();
    foreach(item anItem in myList)
    {
         newList.Add(item.ReturnCopy());
    }
    

    这将复制项目中的所有数据,但保留原始数据不变。有很多模式和接口可以提供更好的实现,但我只是想让您了解一下它是如何工作的。

    假设这些对象都实现了
    IClonable
    (不是很多对象都会实现)并且有合适深度的克隆的合理实现。您有包含相同元素的独立列表。难怪如果更改元素,它会更改(无论您使用什么列表访问此元素)。Clone()是执行/实现此任务的典型方法。我知道,我知道。克隆的问题在于它增加了解释的复杂性,而这不是必需的。如果我引入克隆,我将不得不谈论浅拷贝和深拷贝,而这不是我想在这个答案中讨论的内容。
    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
    
    }