我遇到了一个相当奇怪的问题。我正在迭代一种类型的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 )是readonly,当我写的时候:
model = item;
我正在制作项值的副本。但是当我对模型对象进行计算时,它会在余额列表中产生相同的变化。
我不知道它为什么会影响余额列表。我正在对本地范围的模型对象执行计算。那么为什么那些反映在迭代列表(余额)上。
请帮我解决我的错误。
此致
答案 0 :(得分:3)
model = item;
制作参考,而不是副本。
model.BLNC = model.BLNC - thisQty;
更新引用,即更新原始对象中的值。
toUpdate.Add(model);
将引用添加回原始列表中的原始对象到新列表。
答案 1 :(得分:3)
我假设余额中元素的类型是类类型,而不是 struct 。
因此,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()
。