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.

10 thoughts on “C# 4 idea: Iterator blocks and parameter checking”

  1. Could an approach similar to that used in Spec# be adopted with explicit detailing of preconditions for entry, together with details of the exception to throw if these preconditions are not met?

    E.g.

    public static IEnumerable
    Repeat (TResult element, int count)
    requires count > 1 otherwise ArgumentException;
    {

    }

    or from (http://research.microsoft.com/specsharp/papers/Iterators.pdf)

    IEnumerable FromTo(int b, int e)
    requires b <= e + 1;
    invariant values.Count <= e + 1 – b;
    invariant forall{int i in (0 : values.Count); values[i] == b + i};
    ensures values.Count == e + 1 – b;
    {
    for (int x = b; x <= e; x++)
    invariant values.Count == x – b;
    { yield return x; }
    }

    I’ve always liked Spec#’s way of approaching these things (when I get a chance to look) and would be very interested to hear what you think.

    BTW – started subscribing to your blog after the excellent evening at Ascot with Iterative – thoroughly enjoyed your engaging talk and being a small part of a linq expression! Thank you.

    Neil

  2. I really like the idea and the design. I’ve hit this several times in the past and it usuually takes me a second or two to get past the idea of MoveNext() throwing an Argument*Exception.

    Separating this out into a completing seperate block provides a nice clean way to do validation.

    I’m stuck on the word “do” though because I don’t feel like it’s instructive enough. This would be a contextual keyword so why limit it to existing keywords. How about “yield validate”?

  3. “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.”

    As a side note, this is similar to what Microsoft did when they wrote the LINQ query operators. Some operator methods check the parameters, and then delegate the processing to private classes.

  4. Neil: using the Spec# approach certainly makes sense if contracts like this make it into the main body of the language. I don’t think I’d want them to be introduced *just* for iterator blocks though. Of course, one problem of implementing my proposal (without Spec# contracts) is that if contracts are added later, my syntax becomes obsolete.

    On the other hand, it’s possible that there are other things which *might* make sense to do immediately, beside parameter checking. Logging is the only one I can think of immediately…

  5. Jared: I seem to remember there’s a good reason for the second part of a “yield-statement-phrase” being a keyword. I can’t think of any ways in which “yield validate” followed by a block would be valid code, but “yield validate;” certainly would be if you had a type called yield. Using a keyword as the second part prevents that situation.

    Fortunately, this kind of detail is one for the language designers, if they decide to go with the idea at all. (I strongly suspect it’s an idea which has come up before – I’m not daft enough to think I’m likely to invent genuinely original concepts in this area.)

  6. This may be a stupid question but why are iterators, LINQ queries etc deferred execution?

  7. Imagine they didn’t defer execution, and examine a LINQ to SQL example which contains multiple method calls (Where, Select etc). If each method call had to operate immediately, you would never get the benefits of LINQ – you wouldn’t get the whole query translated into SQL, you’d get one part at a time.

    For instance, if you do a join and then a where, you’d end up getting the whole contents of the join back from the database – far from ideal!

    Likewise deferred execution is necessary for streaming. Imagine if (in LINQ to Objects) Select had to execute immediately. It would have to store the data somewhere, making a copy. Because it only actually fetches data when it’s asked for it, it is able to only process data as it flows through.

    Sorry, that’s not terribly clear – but I suspect if you think about it further, you’ll get it. Just imagine trying to write it in a non-deferred fashion, and then see how evil the whole thing gets.

  8. It’s clear enough :) I get the idea of only fetching the data when it is asked for and the issue involved if it wasn’t deferred.

  9. There are enough “one-off” solutions in C# already. It would be much better to introduce a general construct that allow clearly specify contract. And it would be even better if this construct would be part of the method specification and not of the method body. I. e. it should be possible to include it into declaration of the methods in interfaces as well as into declaration of delegates.

  10. @al0: That’s fine for cases which can be easily expressed without extra logic, e.g. null argument checks – but what about more complicated cases?

Comments are closed.