Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the proper pattern for handling Enumerable objects with a yield return?

Does there exist a standard pattern for yield returning all the items within an Enumerable?

More often than I like I find some of my code reflecting the following pattern:

    public IEnumerable<object> YieldReturningFunction()
    {

        ...
        [logic and various standard yield return]
        ...

        foreach(object obj in methodReturningEnumerable(x,y,z))
        {
            yield return obj;
        }

    }

The explicit usage of a foreach loop solely to return the results of an Enumerable reeks of code smell to me.

Obviously I could abandon the use of yield return increasing the complexity of my code by explicitly building an Enumerable and adding the result of each standard yield return to it as well as adding a the range of the results of the methodReturningEnumerable. This would be unfortunate, as such I was hoping there exists a better way to manage the yield return pattern.

like image 745
rheone Avatar asked Nov 15 '12 17:11

rheone


2 Answers

No, there is no way around that.

It's a feature that's been requested, and it's not a bad idea (a yield foreach or equivalent exists in other languages).

At this point Microsoft simply hasn't allocated the time and money to implement it. They may or may not implement it in the future; I would guess (with no factual basis) that it's somewhere on the to do list; it's simply a question of if/when it gets high enough on that list to actually get implemented.

The only possible change that I could see would be to refactor out all of the individual yield returns from the top of the method into their own enumerable returning method, and then add a new method that returns the concatenation of that method and methodReturningEnumerable(x,y,z). Would it be better; no, probably not. The Concat would add back in just as much as you would have saved, if not more.

like image 115
Servy Avatar answered Sep 21 '22 01:09

Servy


Can't be done. It's not that bad though. You can shorten it to a single line:

foreach (var o in otherEnumerator) yield return o;

Unrelated note: you should be careful of what logic you include in your generators; all execution is deferred until GetEnumerator() is called on the returned IEnumerable. I catch myself throwing NullArgumentExceptions incorrectly this way so often that I thought it was worth mentioning. :)

like image 44
gotopie Avatar answered Sep 17 '22 01:09

gotopie