3

I have a list of objects and I'm doing a foreach on the list and I'm sending each object to a method that modifies the object and returns it; like this:

foreach (MyObjectModel o in TheMasterObject.ListOfMyObjectModel)
{
  o = MyMethod(o);
}

That doesn't work. What I want to do is replace the object I'm iterating on with the modified version that gets returned by MyMethod.

What do I need to change?

Thanks.

frenchie
  • 51,731
  • 109
  • 304
  • 510
  • possible duplicate of [Why is The Iteration Variable in a C# foreach statement read-only?](http://stackoverflow.com/questions/776430/why-is-the-iteration-variable-in-a-c-sharp-foreach-statement-read-only) – Jason Down Jan 07 '12 at 16:40

5 Answers5

3

You cannot reassign to the loop variable, and reassigning the variable wouldn't affect the object inside the list anyway. If you need to write over the object in a list, use a for loop.

for (int index = 0; index < list.Count; index++)
{
     var obj = list[index];
     list[index] = MyMethod(obj);
}
Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • This thread will explain why you can't use a `for..each` loop in the way you tried initially http://stackoverflow.com/questions/5650705/in-c-why-cant-i-modify-the-member-of-a-value-type-instance-in-a-foreach-loop – keyboardP Jan 07 '12 at 16:43
  • And what if I want to remove obj from the list? – frenchie Jan 07 '12 at 16:49
  • That's a separate question, look for duplicates on it. But the answer I might suggest is loop over the list *backwards* and use the `RemoveAt` method. Might look something like `for (int index = list.Count - 1; index >= 0; index--) { list.RemoveAt(index); }` Or maybe you just use `RemoveAll` without a loop and pass in a delegate or lambda expression for the removal criteria. – Anthony Pegram Jan 07 '12 at 16:53
2

You cannot do it like this. C# does not allow modifying the iteration variable of the foreach. Your best option is to hold a secondary list and put the modified values in there and then replace the initial list. Alternatively, if your data structure allows direct indexing, you can replace the foreach with a for and then you will be able to assign the object directly.

Tudor
  • 61,523
  • 12
  • 102
  • 142
0

If MyObjectModel is a class (not a struct) then you don't need to reassign it. A class is a reference type which means your method will get a pointer to the object in the collection. Any modifications you do in the method will be done on the actual object in the list. You don't need to replace it.

If it's a completely new object you are returning, then do what Anthony Pegram is suggesting.

x0n
  • 51,312
  • 7
  • 89
  • 111
0
for (int i =0; i < TheMasterObject.ListOfMyObjectModel.size(); ++i) {
    TheMasterObject.ListOfMyObjectModel.set(i, MyMethod(TheMasterObject.ListOfMyObjectModel.get(i)));
}

I wrote this with java thinking, if some changes need to let it work on C#, be my guest

Adel Boutros
  • 10,205
  • 7
  • 55
  • 89
0

Use a for-loop instead of an iterator.

for (int i = 0; i < objectModels.Count; i++) {
  objectModels[i] = MyMethod(objectModels[i]);
}

As for the why, this questions explains it: Why is the iteration variable readonly

Hope this helps Y

Community
  • 1
  • 1
Yoeri
  • 1,876
  • 15
  • 24