Hacking the foreach loop
What would happen if you updated a List<T>
4294967295 times?
To follow along, you need to have read this tut first.
_version is an Int32
_version
is an int
, it’s also never wrapped in a checked block which means it can overflow.
Let’s look at what happens if you update a list 4294967295 times:
The loophole
When you update a list that many times, the _version
ends up being one less than its initial value.
What this means is, the next time the list is updated, the _version
is back to what it was at the start.
Within the list, it thinks it hasn’t been updated at all.
The list can therefore be updated, however on the next iteration when it’s updated, the _version
is no longer the same as what’s in the Enumerator
.
This means that on the 3rd iteration, the MoveNext()
method will throw an exception.
I can’t think of how this could ever accidentally happen in a real situation, but it’s interesting none the less.
Why not stop developers from overflowing _version?
If _version
was wrapped in a checked block, it would limit the number of times a List<T>
could be updated.
The compiler team decided to allow any number of updates to happen, by allowing _version
to cycle through all its available values.
I think the compiler team rightfully assumed no one would ever happen to try to update a List<T>
right after it has been updated 4294967295 times.
A much more efficient way
The code described earlier could theoretically be written by a new developer who is not trying to break the rules.
Obviously the exact code would not be written, but there could be some complex mathematical algorithm that would result in similar code.
If you are deliberately trying to break the rules, you could use Reflection to update _version
instead.