Search code examples
c#thread-safetyyield-return

Is C#'s yield return thread safe with a Custom IEnumerator?


I have a simple concept of a customized IEnumerator class providing an enumeration of struct/value types. (int, datetime, enum, etc)

class MyNumer : IEnumerator<int>
{
   public MyNumer(int start, int end) { _start = start; _end = end; }
   int _start;
   int _end;

   //Please just assume i've implemented the rest of IEnumerator, this is the only element that is 
   //pertinent to the question

   public bool MoveNext()
   {
      if (this.Current == 0) this.Current = _start;
      else if (this.Current <= _end) this.Current++;
      return this.Current <= _end;
   }
}

class ThreadedClass
{
   public IEnumerable<int> GetNumbers(int start, int end)  //this method can be called from multiple threads
   {
      IEnumerator<int> numer = new MyNumer(start, end);
      while (numer.MoveNext()) yield return numer.Current;
   }
}

What I'm concerned about is provided this example, if :

  1. Thread1 calls "myThreadedClass.GetNumbers(1, 10)"
  2. Thread2 calls "myThreadedClass.GetNumbers(30, 40)"
  3. Thread3 calls "myThreadedClass.GetNumbers(70, 100)"

Will I get three separate, distinct IEnumerable returned, or will the threads collide on the "yield return"?


Solution

  • Not only you will get three distinct IEnumerable<int> objects, but also each time you enumerate each of them a new IEnumerator<int> will be created, with its own distinct internal instance of the MyNumer class. So there would be no thread safety issue even if all three threads were sharing the same IEnumerable<int> instance, returned by a single invocation of the GetNumbers method.