我遇到了一个相当奇怪的问题。我正在迭代一种 List,在我的循环中,我将迭代器变量分配给另一个局部对象。现在,更改该本地对象中的任何内容都会导致循环迭代的 List 发生变化。让我用代码示例来清除这一点。
var balances = DBHelperADO.Select("select * from Orders");
// balances is of type List<MyModel>
foreach (var item in balances)
{
MyModel model = new MyModel();
model = item;
var thisQty = details.Where(x => x.Code == item.Code).Sum(x => x.QTY);
// details is another List<MyModel> holding values from the GUI
model.BLNC = model.BLNC - thisQty;
model.VAL = (model.BLNC == 0) ? 0 : model.VAL - (thisQty * model.RATE);
model.TABLE = "Orders";
toUpdate.Add(model); // toUpdate is a List<MyModel>
}
现在我的理解是迭代器变量(在本例中为项目)是只读的,当我编写时:
模型 = 项目;
我正在复制我的项目值。但是当我对模型对象进行计算时,它会导致余额列表上的相同更改。
我不明白为什么它会影响余额列表。我正在对本地范围的模型对象执行计算。那么为什么这些反映在迭代列表(余额)上。
请帮助我做错了什么。
问候
我假设余额中元素的类型是类类型而不是结构。
因此,存储在 item
和 model
中的内容是对此类实例的引用。分配model = item;
时,不会复制实例,而只会复制对实例的引用。
现在,当您通过model.BLNC = ...
访问该实例的属性时,您将更改原始实例的属性。这和打电话给item.BLNC = ...
是一样的
初始行MyModel model = new MyModel()
相当过时,因为您覆盖了对该新实例的引用。
要制作真实的副本,您可以尝试类似
MyModel model = new MyModel
{
BLNC = item.BLNC,
VAL = item.VAL,
TABLE = "Orders"
// ... copy further properties
};
您还可以使用 LINQ Select
语句完全重写循环,如下所示:
var toUpdate = balances.Select(item =>
{
var thisQty = details.Where(x => x.Code == item.Code).Sum(x => x.QTY);
var blnc = item.BLNC - thisQty;
return new MyModel
{
BLNC = blnc,
VAL = (blnc == 0) ? 0 : item.VAL - (thisQty * item.RATE),
RATE = item.RATE,
TABLE = "Orders"
};
}).ToList();
您可能需要将 MyModel
类的更多属性从item
复制到新实例。如果嵌套查询出现问题,则可能需要使用 balances.AsEnumerable()
。
model = item;
引用,而不是副本。
model.BLNC = model.BLNC - thisQty;
更新引用,即更新原始对象中的值。
toUpdate.Add(model);
将原始列表中对原始对象的引用添加回新列表。