6

Say I have the following code (context narrowed down as to keep the question scope limited)

public static IEnumerable<Color> GetThemColors(){
    var ids = GetThePrimaryIds();
    foreach (int id in ids){
        yield return GetColorById(id);
    }
    ids = GetTheOtherIds();
    foreach (int id in ids){
        yield return GetOtherColorsById(id);
    }
}

I would like to rewrite them to something like this (which off course doesn't compile

public static IEnumerable<Color> GetThemColors(){
    GetThePrimaryIds().Select(id=>yield return GetColorById(id));
    GetTheOtherIds().Select(id=>yield return GetOtherColorsById(id));       
}

The key point being that in my first snippet I have two foreach enumerators yielding, which I don't know how to do in linq without loosing my lazy-loading features.

Boris Callens
  • 90,659
  • 85
  • 207
  • 305

1 Answers1

15

You want Concat:

return GetThePrimaryIds().Select(id => GetColorById(id)).Concat(
    GetTheOtherIds().Select(id => GetOtherColorsById(id)));

Also note that you don't need yield return in lambdas.

Pavel Minaev
  • 99,783
  • 25
  • 219
  • 289
  • Thanks, didn't realize the concat was lazy – Boris Callens Dec 01 '09 at 09:25
  • 1
    As far as I know all the methods on Enumerable that return an IEnumerable are lazy. – Joren Dec 01 '09 at 10:07
  • True, but I assumed for some reason Concat would return a IList – Boris Callens Dec 01 '09 at 10:30
  • 1
    It should be noted that the call to `GetTheOtherIds()` is _not_ lazy, i.e. it will first call `GetThePrimaryIds()`, then call `GetTheOtherIds()`, then call `Concat()`. However, if the methods themselves are lazy, then it's not a problem. – Pavel Minaev Dec 01 '09 at 16:53
  • @borisCallens: if that were the case, it would have been declared as returning `IList` or `ICollection` – sehe Oct 24 '11 at 13:43