Why is foreach loop Read-Only in C#

后端 未结 3 1273
北海茫月
北海茫月 2020-11-29 11:22

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:

         


        
相关标签:
3条回答
  • 2020-11-29 11:47

    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
    0 讨论(0)
  • 2020-11-29 11:51

    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.

    0 讨论(0)
  • 2020-11-29 11:59

    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 讨论(0)
提交回复
热议问题