C#: yield return within a foreach fails - body cannot be an iterator block

p.campbell picture p.campbell · Mar 10, 2010 · Viewed 21.5k times · Source

Consider this bit of obfuscated code. The intention is to create a new object on the fly via the anonymous constructor and yield return it. The goal is to avoid having to maintain a local collection just to simply return it.

public static List<DesktopComputer> BuildComputerAssets()
{           
    List<string> idTags = GetComputerIdTags();

    foreach (var pcTag in idTags)
    {
        yield return new DesktopComputer() {AssetTag= pcTag
                                          , Description = "PC " + pcTag
                                          , AcquireDate = DateTime.Now
                                           };
    }            
}

Unfortunately, this bit of code produces an exception:

Error 28 The body of 'Foo.BuildComputerAssets()' cannot be an iterator block because 'System.Collections.Generic.List' is not an iterator interface type

Questions

  • What does this error message mean?
  • How can I avoid this error and use yield return properly?

Answer

SLaks picture SLaks · Mar 10, 2010

You can only use yield return in a function that returns an IEnumerable or an IEnumerator, not a List<T>.

You need to change your function to return an IEnumerable<DesktopComputer>.

Alternatively, you can rewrite the function to use List<T>.ConvertAll:

return GetComputerIdTags().ConvertAll(pcTag => 
    new DesktopComputer() {
        AssetTag    = pcTag,
        Description = "PC " + pcTag,
        AcquireDate = DateTime.Now
    });