Foreach循环内的计算影响迭代列表值

时间:2016-07-05 09:09:47

标签: c# foreach

我遇到了一个相当奇怪的问题。我正在迭代一种类型的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;

  

我正在制作值的副本。但是当我对模型对象进行计算时,它会在余额列表中产生相同的变化。

我不知道它为什么会影响余额列表。我正在对本地范围的模型对象执行计算。那么为什么那些反映在迭代列表(余额)上。

请帮我解决我的错误。

此致

2 个答案:

答案 0 :(得分:3)

model = item;制作参考,而不是副本

model.BLNC = model.BLNC - thisQty;更新引用,即更新原始对象中的值。

toUpdate.Add(model);引用添加回原始列表中的原始对象到新列表。

答案 1 :(得分:3)

我假设余额中元素的类型是类型,而不是 struct

因此,itemmodel中存储的内容是该类的实例引用。当您分配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()