Post permalink

VB already does allow "iterator anonymous methods" aka "iterator lambdas" in the CTP. It does this for reasons of symmetry. It also allows "yield" inside try/catch blocks for the same reason. The question is whether these two enhancements should be back-ported to C#...

BACKGROUND:

C# had iterators ages ago. It used the old implementation strategy to implement them. This was a compile-time transformation that's complicated and limited (doesn't work with try/catch; is too hard to stretch to lambdas) but it generates good code.

The CTP introduced async, and also introduced iterators to VB. It used the new implementation strategy to implement them. This is a compile-time transformation pioneered by Axum. It's straightforward and flexible (does allow await/yield inside try/catch; is okay to stretch to lambdas). The code it generates takes a few extra IL opcodes to execute compared to the old implementation strategy.

VB uses the new implementation strategy for iterators+async. C# in the CTP also uses the new implementation strategy for both (although we didn't flip the switch to enable try/catch, nor iterator lambdas, since we didn't want the CTP to promise more than we actually plan to deliver).

QUESTION:

The question is: should C# change to use the new implementation strategy, and allow yield inside try/catch blocks and allow iterator lambdas? Or should it stick with the old implementation strategy for iterators?

PRO: It'd be more symmetrical if C# allowed iterators to have the same freedoms as async.

CON: The concept of an iterator lambda is rather subtle.

CON: The concept of a yield inside try/catch is strange. That's because if the body of the "foreach" loop throws an exception, it will not be caught by any Catch handlers in the iterator method -- but it will be caught by Finally handlers!! (that's because Finally handlers are run by IEnumerator.Dispose).

PRO: The old implementation strategy had a huge bug-tail in C#, and there are still bugs that haven't been fixed (to do with whether finally handlers are called zero times, once, or twice!)

CON: Much of the LINQ framework is implemented using the old C# implementation strategy. If we switched C# iterators to use the new strategy, then we'd impair EVERYONE'S performance.

As Eric Lippert says, every new language proposal comes with a built-in penalty of -500 points. We have to decide whether the advantages it brings outweigh the negatives, and also if they're sufficiently compelling to win over that -500 points.

At the moment, the advantages of changing C#'s iterator implementation don't quite seem big enough. But if anyone can post with compelling scenarios where it would help, then please do, since that will strongly influence our decision.