复制与参考

时间:2012-08-22 16:03:18

标签: c#

为什么这段代码会导致shipment.Items.Count和combinedShipment.Items.Count等于零?

private static InboundShipment CombineLikeIsbns(InboundShipment shipment)
{
    // shipment.Items has a count of 3

    var distinctIsbns = shipment.Items.Select(i => i.ISBN).Distinct().ToList();

    var combinedShipment = shipment;
    combinedShipment.Items = new List<InboundShipmentItem>();

    // Now both combinedShipment and shipment have an empty List in the .Items property

    ...

    return combinedShipment;
}

[编辑] 当我将combinedShipment.Items设置为相同时,我可以做些什么来避免出货。物品设置为新列表?

3 个答案:

答案 0 :(得分:5)

本声明:

var combinedShipment = shipment;

shipment的值复制到combinedShipment。假设InboundShipment是一个类,shipment的值是引用 - 而不是对象本身。

所以现在我们有两个变量都引用同一个对象。使用哪个变量来对对象进行更改无关紧要 - 通过两个变量可以看到的变化。

如果要创建原始对象的新“副本”,则必须明确地执行此操作。由于您没有向我们提供有关InboundShipment类型的更多信息,因此很难确切地知道您需要在此处做些什么。

有关详细信息,请参阅我的article on value types and reference types。请注意,这是C#和.NET的重要部分,在进一步发展之前你应该对它充满信心 - 诸如LINQ(带有lambda表达式,延迟执行等)的高级主题将很难明白,直到你掌握了基础知识。

答案 1 :(得分:1)

该行

var combinedShipment = shipment; 

将combinedShipment引用设置为指向与货件相同的实例。因此,当您清除combinedShipment上的项目时,它会为该单个实例清除它们。

答案 2 :(得分:1)

作业var combinedShipment = shipment;会导致combinedShipmentshipment引用完全相同的对象。这有点像在同一个纸板箱上粘贴两个不同的标签。

因此,您从标有combinedShipment的框中取出所有项目的以下行也会导致标记为shipment的框被清空。因为它们只是带有两个不同标签的同一个盒子。

如果要创建具有不同项目的新货件对象,则需要首先执行以下操作:创建新的货件对象。

var combinedShipment = new InboundShipment();

实际代码可能看起来不完全一样。假设您希望combinedShipment的某些属性与shipment的属性相同,则必须手动确保发生这种情况。根据{{​​1}}的设计方式,这需要将所需的值传递给构造函数,通过属性设置所需的值,或者两者兼而有之。