Suggested 18:foreach cannot replace for
The two advantages of foreach are mentioned in the previous recommendation: The syntax is simpler, the Dispose method is called by default, and we strongly recommend that you use foreach more in actual code writing. However, the recommendation also has a scenario that is not appropriate.
There is a problem with foreach: it does not support adding or deleting a collection when looping. For example, running the following code throws an exception InvalidOperationException:
list<int> list=new list<int> () {0,1,2,3 }; foreach (int in list) { list. Remove (item); Console.WriteLine (item); }
Instead, use the For loop
for (int0; i < list.) Count; i++) { list. Remove (List[i]); Console.WriteLine (List[i]); }
The Foreach Loop uses an iterator to iterate through the collection, which maintains a control over the collection version within the FCL provided by the drop instead of the internal. So what is a collection version? In simple terms, it's actually a variable that's shaped, Any additions or deletions to the collection will make the version number plus 1.foreach calls the MoveNext method to traverse the element, the version number is detected inside the MoveNext method, and if the version number is detected, a InvalidOperationException exception is thrown.
This is not a problem if you use a for loop. For direct use of the indexer, it does not judge the collection version number, so there is no exception to the change of the collection (except, of course, an exception that exceeds the index length).
Because the For loop and the Foreach Loop implementation are different (the former indexer, the latter iterator), the performance controversy over both has never stopped. However, even if it is controversial, both sides acknowledge that both have a loss of time and memory, especially when it comes to generic collections, where the loss is at the same quantity level.
In the case of type list<t>, the indexer looks like this:
[__dynamicallyinvokable] PublicT This[intIndex] {[Targetedpatchingoptout ("performance critical to inline across NGen image boundaries"), __dynamicallyinvokable]Get { if(Index >= This. _size) {throwhelper.throwargumentoutofrangeexception (); } return This. _items[index]; } [Targetedpatchingoptout ("performance critical to inline across NGen image boundaries"), __dynamicallyinvokable]Set { if(Index >= This. _size) {throwhelper.throwargumentoutofrangeexception (); } This. _items[index] =value; This. _version++; }}
The iterator looks like this:
[__dynamicallyinvokable] Public BOOLMoveNext () {List<T> list = This. List; if(( This. Version = List._version) && ( This. Index <list._size)) { This. Current = list._items[ This. index]; This. index++; return true; } return This. Movenextrare ();}
[__dynamicallyinvokable] Public T current{ [__dynamicallyinvokable, Targetedpatchingoptout ("performance critical to Inline this type of method across NGen image boundaries")] get {
returnthis. Current;
You can see that a generic array is maintained inside the,list<t> class:
Private T[] _items;
Whether it is a for loop or a foreach loop, the inside is access to the array, and the iterator is simply a one-time version check. In fact, inside the loop, the IL code generated by the two is similar, but, as mentioned at the beginning of this recommendation, because of version detection, the Foreach loop does not replace the for loop.
Turn from: 157 recommendations for writing high-quality code to improve C # programs Minjia
"Go" write high-quality Code 157 recommendations for improving C # programs--suggest that 18:foreach is not a substitute for