5

Using yield return turns a method into an iterator. The return type of an iterator must be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

I have found that an iterator can only be used in a foreach loop if it returns one of the IEnumerable types. Given this limitation, when would it make sense to choose an IEnumerator return type instead of an IEnumerable?

user200783
  • 13,722
  • 12
  • 69
  • 135
  • 1
    The only place I've seen an iterator method returning an `IEnumerator` is for [Unity's coroutines](https://docs.unity3d.com/Manual/Coroutines.html). I assume this is because they're (ab)using the iterator machinery to do something different, and don't want people accidentally thinking they should be looping over the coroutine. – canton7 Apr 15 '20 at 12:36
  • I acutally thought that this code: https://dotnetfiddle.net/KOMtuL - would crash, since I am only returning the interface `IEnumerator` so who acutally implements the method `MoveNext()` ?!? Magic? – Rand Random Apr 15 '20 at 12:42
  • 1
    @RandRandom [Demystified](https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA+ABATARgLABQGADAAQY4B0AwhADZ0xgAuAlhAHYDOA3ISeRwo+BAJDjx/AMzksggOyEA3oVHYsqlWNEA3AIZRSCUgF5SAMQgQAFAEoR4gO4ALVo2sJKAWQg6YAORgEZjtbVXEKAE4PGgBXKFgOZntVAF9VVQwZCiRSAEkAUQ5YgFsYKD1maAsrO01wihxyeVIAIgAJGAYIUgB1aDoAE1aHdIJUoA===) – canton7 Apr 15 '20 at 12:44
  • 1
    @RandRandom The block of code will be compiled into an IEnumerator state machine that will handle the MoveNext and Current. – juharr Apr 15 '20 at 12:44

1 Answers1

5

Pretty rarely, to be honest. The only times I've seen it used that way is when special-casing things for some reason in the GetEnumerator() method (before firing up the iterator block machinery), but still wanting an iterator block for the actual implementation, i.e.

public IEnumerator<T> GetEnumerator()
{
    if (someScenario) return SomethingSpecialPerhapsEmptyArrayEnumerator();
    if (anotherScenario) ThrowSomeException();
    return DoTheThing();
}
private IEnumerator<T> DoTheThing()
{
    // ... yield return
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900