0

I am encountering a rather strange problem. I am iterating over a type of List and within my loop I assign the iterator variable to another local object. Now changing anything in that local object is causing changes in the List on which loop is iterating. Let me clear this with a code sample.

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>                    
}

Now my understanding is that the iterator variable (in this case the item) is readonly and when I write:

model = item;

I am making a copy of my item values. But when I do the the calculations on the model object it causes the same changes on the balances list.

I am not getting why its effecting the balances list. I am performing calculations on local scoped model object. Then why those are reflecting on the iterating list (balances).

Please help me what I am doing wrong.

Regards

2 Answers 2

3

I assume that the type of the elements in balances is a class type and not a struct.

So what is stored in item and model is a reference to an instance of that class. When you assign model = item; you do not copy the instance, but only the reference to the instance.

When you now access the property of that instance via model.BLNC = ... you change the properties of the original instance. It's the same as calling item.BLNC = ...

The initial line MyModel model = new MyModel() is rather obsolete, as you overwrite the reference to that new instance.

To make a real copy you can try something like

MyModel model = new MyModel
{    
    BLNC = item.BLNC,
    VAL = item.VAL,
    TABLE = "Orders"
    // ... copy further properties
};

You could also completely rewrite your loop with a LINQ Select statement like this:

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();

You may have to copy more properties of your MyModel class from item to the new instance. And it may be necessary to use balances.AsEnumerable() if there are problems with nested queries.

Sign up to request clarification or add additional context in comments.

1 Comment

THANKS a lot. That LINQ select is really elegant.
3

model = item; makes a reference, not a copy.

model.BLNC = model.BLNC - thisQty; updats the reference, i.e. it updates the value in the original object.

toUpdate.Add(model); adds the reference back to your original object in the original list to the new list.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.