“copy”列表所做的更改反映在原始列表上 - c#

4

我有两个列表,一个是原始列表,另一个是复制列表。我复制了原始列表,因为有一个原因:

我需要处理/操作原始列表中的数据,但是我不应该对其进行编辑。所以我创建了原始列表的副本来进行操作。但是一些我在复制列表上做的更改仍然会修改原始列表。

这是我的代码:

forPrintKitchenOrders = new List<OrderTemp>();
foreach (var itemss in forPrintKitchen)
{
  forPrintKitchenOrders.Add(itemss); // HERE I AM ADDING ITEMS TO ANOTHER LIST BECAUSE I DON'T WANT TO EDIT ORIGINAL LIST (Change quantity etc)
}

if (forPrintKitchen.Count > 0)
{

  foreach (var item in forPrintKitchenOrders.ToList())
  {
      foreach (var item2 in mainList)
      {
          if (item2.MainProductID == Convert.ToInt32(item._articleCode))
          {
              //I don't know why this is happening. I loop another list (copy of original list, because I didn't want to harm original list), and when I find certain item I am reducing quantity (-1),
              //And later I realized and saw while I was debugging, that the value of quantity in my original "forPrintKitchen" list is also edited, I don't know how changed reflected there..

              int calculate = Convert.ToInt32(item._quantity)-1; //this block is making me trouble, here I am reducing quantity and later that reflects to my forPrintKitchen list even if I am editing and looping //forPrintKitchenOrders(original's copy)
              item._quantity = calculate.ToString();
          }
      }
  }
    foreach (var items in forPrintKitchen) //THIS IS MY ORIGILAN LIST AND SHE SHOULD NOT BE EDITED WHEN I EDIT "forPrintKitchenOrders" item
    {
    //Original List
        OrdersKitchen kitchen = new OrdersKitchen();
        kitchen.ProductID = Convert.ToInt32(items._articleCode);
        kitchen.UserID = Util.User.UserID;
        kitchen.UserName = Util.User.FirstName
        kitchen.LastName = Util.User.LastName
        kitchen.BillID = bill.BillID;
        kitchen.Quantity = Convert.ToInt32(items._Quantity);
        OrdersKitchen.Add(kitchen);
    }
    foreach (var itemss in mainList)
    {

        OrdersKitchen kitchen2 = new OrdersKitchen();
        kitchen2.ProductID = Convert.ToInt32(itemss.MainProductID);
        kitchen2.UserID = User.UserID;
        kitchen2.UserName = Util.User.FirstName;
        kitchen2.LastName = Util.User.LastName;
        kitchen2.BillID = bill.BillID;
        kitchen2.Quantity = Convert.ToInt32(0); //HARDCODE ZERO
        OrdersKitchen.Add(kitchen2);
    }
 }

mainList.Clear();
//forPrintKitchenOrders.Clear();
}

在我看到回复后,我阅读了@sachin的帖子,并编写了类似于他们的代码。这样做可以吗?它看起来现在正在运行,但我不确定这个解决方案是否可行?

foreach (var itemss in forPrintKitchenOrders)
{
    forPrintKitchenOrders.Add(new OrderTemp(itemss._articleCode,itemss._name,itemss._quantity,itemss._amount));
}

public class OrderTemp
{
        public string _articleCode;
        public string _name;
        public string _quantity;
        public double _amount;

        public OrderTemp(string articleCode, string name, string quantity, double amount)
        {
            _articleCode = amount;
            _name = name;
            _quantity = quantity;
            _amount = amount;
        }
}

4
这是两个列举相同对象的清单。你需要创建一个新的集合,它引用了旧集合中相同的对象。如果你在第一个集合中更改某个对象的属性,则第二个集合中的该对象也会被更改。这是因为你使用的对象是引用类型而不是值类型。 - Zein Makki
1
请查看此处:https://dev59.com/zWYr5IYBdhLWcg3wB12h - Clemens
1
正如@user3185569在第一篇帖子中的评论所说,您并没有将对象从一个列表复制到另一个列表。您只是复制了引用。您需要将forPrintKitchenOrders.Add(itemss);更改为forPrintKitchenOrders.Add(itemss.Clone()); - Rumpelstinsk
3个回答

5
您所提到的“复制列表”实际上并不是一个副本
集合中的元素引用的是原始集合中相同的对象
您需要将复制foreach循环替换为以下内容:
foreach (var item in forPrintKitchen)
{
    forPrintKitchenOrders.Add(item.Clone()); // The clone method should return a new Instance after copying properties from item.
}
Clone方法应该创建一个new实例并复制正在克隆的实例的每个属性,然后返回新创建的实例。
基本上,您需要在OrderTemp类中定义一个名为Clone(名称不重要)的方法,如下所示:
public class OrderTemp
{
    /*  other members of the class */
    public OrderTemp Clone()
    {
        return new OrderTemp
        {
            property1 = this.property1;
            property2 = this.property2;
            /* and so on */
        };
    }
}

通过遵循您的帖子,我将编辑我的问题并发布我找到的解决方案,但我不确定是否正确。所以你能看一下吗? - Roxy'Pro
你能回答我一下,在我的帖子的编辑部分写的内容是否正确吗? - Roxy'Pro
你能给我一点解释为什么它实际上有效吗? :) 谢谢 - Roxy'Pro
@Roxy'Pro 这里的关键是 new 操作符。当你使用 new 操作符创建一个实例时,你创建的实例与原始实例不同。 - sachin

2

你基本上创建了一个浅拷贝。这意味着它将复制所有简单类型,如引用和通用类型,但不会复制对象内容。

作为解决方案,您需要完全复制您的对象:

foreach (var itemss in forPrintKitchen)
{
  forPrintKitchenOrders.Add(new OrderTemp(){ /*copy itemss here*/ });
}

我喜欢使用AutoMapper来完成这个任务,但如果您不想在项目中使用框架,您可以在OrderTemp类型和所有必要的嵌套类型上实现IClonable并调用Clone()方法。


0

你复制了列表,但是副本仍然包含对相同对象的引用;对象本身并没有被复制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接