Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is foreach loop Read-Only in C#

Tags:

c#

loops

Why is foreach loop a read only? I mean you can fetch the data but can't increase++ or decrease--. Any reason behind it? Yes I am a beginner :)

Exmaple:

int[] myArray={1,2,3};
foreach (int num in myArray)
{
  num+=1;
}
like image 384
Jasmine Appelblad Avatar asked Oct 23 '10 15:10

Jasmine Appelblad


2 Answers

That is because foreach is meant to iterate over a container, making sure each item is visited exactly once, without changing the container, to avoid nasty side effects.

See: foreach in MSDN

If you meant why would changes to an element like an integer not affect a container of integers, well this is because the variable of iteration in this case would be a value type and is copied, e.g.:

// Warning: Does not compile
foreach (int i in ints)
{
  ++i; // Would not change the int in ints
}

Even if the variable of iteration was a reference type, whose operations returned a new object, you wouldn't be changing the original collection, you would just be reassigning to this variable most of the time:

// Warning: Does not compile
foreach (MyClass ob in objs)
{
  ob=ob+ob; // Reassigning to local ob, not changing the one from the original 
            // collection of objs
}

The following example has the potential to actually modify the object in the original collection by calling a mutating method:

// Warning: Does not compile
foreach (MyClass ob in objs)
{
  ob.ChangeMe(); // This could modify the object in the original collection
}

To avoid confusion with regard to value vs reference types and the scenarios mentioned above (along with some reasons related to optimization), MS chose to make the variable of iteration readonly.

like image 122
Michael Goldshteyn Avatar answered Oct 11 '22 20:10

Michael Goldshteyn


Because the current element is returned by value(i.e. copied). And modifying the copy is useless. If it is a reference type you can modify the content of that object, but can't replace the reference.

Perhaps you should read the documentation of IEnumerable<T> and IEnumerator<T>. That should make it clearer. The most important bit is that IEnumerable<T> has a property Current of type T. And this property has only a getter, but no setter.

But what would happen if it had a setter?

  • It would work well with arrays and Lists
  • It wouldn't work well with complex containers like hashtables, ordered list because the change causes larger changes in the container(for example a reordering), and thus invalidates the iterator. (Most collections invalidate the iterators if they get modified to avoid inconsistent state in the iterators.)
  • In LINQ it does make no sense at all. For example with select(x=>f(x)) the values are results of a function and have no permanent storage associated.
  • With iterators written with the yield return syntax it doesn't make sense either
like image 40
CodesInChaos Avatar answered Oct 11 '22 21:10

CodesInChaos