I suspect this is a matter of practicality rather than feasibility. I suspect there are very, very few times where this restriction is actually an issue that can’t be worked around – but the added complexity in the compiler would be very significant.
There are a few things like this that I’ve already encountered:
- Attributes not being able to be generic
- Inability for X to derive from X.Y (a nested class in X)
- Iterator blocks using public fields in the generated classes
In each of these cases it would be possible to gain a little bit more freedom, at the cost of extra complexity in the compiler. The team made the pragmatic choice, for which I applaud them – I’d rather have a slightly more restrictive language with a 99.9% accurate compiler (yes, there are bugs; I ran into one on SO just the other day) than a more flexible language which couldn’t compile correctly.
EDIT: Here’s a pseudo-proof of how it why it’s feasible.
Consider that:
- You can make sure that the yield return part itself doesn’t throw an exception (precalculate the value, and then you’re just setting a field and returning “true”)
- You’re allowed try/catch which doesn’t use yield return in an iterator block.
- All local variables in the iterator block are instance variables in the generated type, so you can freely move code to new methods
Now transform:
try
{
Console.WriteLine("a");
yield return 10;
Console.WriteLine("b");
}
catch (Something e)
{
Console.WriteLine("Catch block");
}
Console.WriteLine("Post");
into (sort of pseudo-code):
case just_before_try_state:
try
{
Console.WriteLine("a");
}
catch (Something e)
{
CatchBlock();
goto case post;
}
__current = 10;
return true;
case just_after_yield_return:
try
{
Console.WriteLine("b");
}
catch (Something e)
{
CatchBlock();
}
goto case post;
case post;
Console.WriteLine("Post");
void CatchBlock()
{
Console.WriteLine("Catch block");
}
The only duplication is in setting up try/catch blocks – but that’s something the compiler can certainly do.
I may well have missed something here – if so, please let me know!