Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping call to iterator in try/catch when using yield

I need to do some heavy, somewhat fragile logic in a method that I'm implementing as an iterator (using yield):

public IEnumerable<Things> GetMoreThings() {
    while (goodStuffHappens()) {
        Things moreThingsIWant = TemptFateAgain();
        if (moreThingsIWant.Any())
            yield return moreThingsIWant;
    }
}

Out in the calling method, I need to wrap the call to GetMoreThings in try/catch and yield return the result:

try {
    foreach (Things thing in Helpful.GetMoreThings())
        yield return thing;
}

catch (Exception e) {
    //crash, burn
}

The initiated will immediately realize that this is impossible - there is no such thing as a yield inside a try/catch block (only try/finally).

Any recommendations?

like image 677
sq33G Avatar asked Mar 13 '23 07:03

sq33G


1 Answers

Both the answers here were correct. There's no built-in shortcut for this one, you need to tease apart the iterator in a while rather than a for loop in order to separate between the call to Enumerator.MoveNext() and the use of Enumerator.Current.

IEnumerator<Things> iterator = Helpful.GetMoreThings.GetEnumerator();
bool more = true;

while (more) {
    try {
        more = iterator.MoveNext();
    }
    catch (Exception e) {
        //crash, burn
    }

    if (more)
        yield return iterator.Current;
}
like image 123
sq33G Avatar answered Mar 24 '23 02:03

sq33G