Tuesday, March 1, 2011

Changing item in foreach thru method.

Let's start with the following snippet:

Foreach(Record item in RecordList){
  ..
  item = UpdateRecord(item, 5);
  ..
}

The UpdateRecode function changes some field of item and returns the altered object. In this case the compiler throws an exception saying that the item can not be updated in a foreach iteration.

Now the UpdateRecord method is changed so that it returns void and the snippet would look like this:

Foreach(Record item in RecordList){
  ..
  UpdateRecord(item, 5);
  ..
}

In this case the item would be updated because Record is a reference type. But it makes the code unreadable.

The project I'm working on has lots of foreach-loops with the almost the same code over and over, so I would like to create methods that update parts of the records. Is there a nice way to do this? One that make the code more readable instead of trashing it further more?

From stackoverflow
  • If you need to update a collection, don't use an iterator pattern, like you said, its either error prone, or smells bad.

    I find that using a for loop with an index a bit clearer in this situation, as its very obvious what you are trying to do that way.

    Sorskoot : Thanks, I think it's the only right way to go in my situation.
    Robert Rossney : There's absolutely nothing wrong with using an iterator pattern to update the items in a collection. You don't want to add or remove items from the collection while iterating, and that's what the compiler is complaining about.
  • Do you need to update the same list? Could you return a new (updated) enumeration instead?

    foreach(Record item in RecordList){
      ..
      yield return GetUpdatedRecord(item, 5);
      ..
    }
    
    Sorskoot : Thank you for your comment. In my case yield isn't an option. But I shall keep it in mind, it could be usefull...
  • The compiler is complaining that you can't update the collection, not the record. By doing item = UpdateRecord, you are reassigning the iterator variable item.

    I disagree that UpdateRecord(item, 5) is in any way unreadable - but if it makes you feel better, an extension method may make it more clear that you are changing the contents of item.

    static void Update(this Record item, int value) {
       // do logic
    }
    
    foreach (Record item in RecordList) {
       item.Update(5);
    }
    

0 comments:

Post a Comment