C# 4 idea: Iterator blocks and parameter checking

Iterator blocks have an interesting property: they defer execution. When the method (or property) is called, none of your code is executed – it only starts running when MoveNext() is first called.

Deferred execution is a great thing in many ways, but it’s a pain when it comes to parameter checking. If you check parameters within an iterator block, you’ve effectively left a timebomb – the error will be potentially reported a long way from the original source of the problem. (Side-note: this is why I prefer using a cast to as when I know what type something really should be – I’d rather get an InvalidCastException immediately than a NullReferenceException later on.)

One solution to this is to check the parameters in the public method and then call a private method which is implemented with an iterator block. That’s a bit ugly though. It would be nice to be able to specify the parameter checking in an initial block which could only occur at the start of the method – something like this simple implementation of Repeat:

public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
{
    yield do
    {
        if (count < 0)
        {
            throw new ArgumentException(count);
        }
    }
    for (int i=0; i < count; i++)
    {
        yield return element;
    }
}

I’ve chosen yield do for two reasons: it fits in with the rest of the yield pattern, and by using an existing keyword I suspect it reduces/eliminates the chance of this being a breaking change. It’s not ideal from the point of self-description, but do is the closest keyword I could find when I looked at the spec. In a language with begin as a keyword, that would probably be a better choice – or initial. fixed appeals in that the code is fixed in the method rather than being shunted off into the compiler-generated type, but the normal use of fixed is far too different to make this an appealing choice. Any other suggestions are very welcome :)

Is this an important enough change to make it worth including in C# 4? I’m not sure. The negative side is that I suspect relatively few people use iterator blocks much, so it may not have a very wide benefit. The positive side is that it only actually makes any difference to those who do use iterator blocks, and I believe almost all of them would find it a welcome addition. It’s simple to understand, and it makes iterator blocks much easier to use in a “correct” manner when any form of initial checking is involved.

Note, mostly to myself and Marc Gravell: I haven’t checked, but I suspect most of Push LINQ is broken in this respect.

Further note to self – I really need to fix my code formatter to treat yield as a contextual keyword.

Trivia: when is a no-op not a no-op?

Hopefully most readers are familiar with the yield break; statement. Usually, if it appears at the end of a method its a no-op which can be removed with no change in behaviour. For instance:

public IEnumerable<int> Range1 (int start, int count)
{
    for (int i=0; i < count; i++)
    {
         yield return start+i;
    }
    yield break;
}

public IEnumerable<int> Range2 (int start, int count)
{
    for (int i=0; i < count; i++)
    {
         yield return start+i;
    }
}

Can anyone think of a situation where a yield break; directly before the closing brace of a method cannot be removed without breaking the code? (I suggest that early answers are given in ROT-13 to avoid spoiling it for anyone else.)