This is just what puzzled me since I read about iterators on the Jon Skeet website .
A simple performance optimization implemented by Microsoft using their automatic iterators - the returned IEnumerable can be reused as an IEnumerator, preserving the creation of the object. Now, since IEnumerator must be monitoring the state, this is only true on the first retry.
What I cannot understand is why the development team adopted the approach they took to ensure thread safety.
Normally, when I am in a similar position, I would use what I think is simple Interlocked.CompareExchange to ensure that only one thread can change state from "available" to "in process".
Conceptually, it is very simple, one atomic operation, additional fields are not required, etc.
But are project teams suitable? Each IEnumerable saves the managed stream identifier field of the created stream, and then this stream identifier is checked when GetEnumerator is called against this field, and only if it is the same stream, and the first time it is called, IEnumerable can return itself as IEnumerator. It seems harder to reason, imo.
I'm just wondering why this approach was adopted. Lock operations are much slower than two calls to System.Threading.Thread.CurrentThread.ManagedThreadId, so that it justifies the extra field?
Or is there another reason for this, perhaps using memory models or ARM devices or something that I don't see? Maybe the specification has special requirements for implementing IEnumerable? Just sincerely puzzled.
source share