开发者

Why is foreach loop Read-Only in C#

Why is foreach loop a read only? I mean 开发者_StackOverflow中文版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;
}


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.


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


foreach is designed to visit each item in a collection exactly once, and does not use an explicit "loop index"; if you want more control over the loop and have a loop index, use for.

EDIT: You can change the items in the collection being iterated on inside a foreach loop. For example:

foreach(Chair ch in mychairs)
{
    ch.PaintColour = Colour.Green; //this alters the chair object *in* the collection.
}

You cannot, however, add or remove items to/from the collection.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜