Duck Notation

I have been working with the C# and VB teams on design guidelines for LINQ. We started to talk about the so called Query Pattern, which describes what you need to do if you want a custom type to support the new query operators (select, where, group by, etc.).

The query operators use duck typing to determine whether they can operate on a type or not. This means that instead of implementing an interface (static typing) a queryable type will need to have a set of members that follow a specified set of conventions (naming, parameter and return types, etc).

For example, the C#’s foreach operator already uses duck typing. This might be surprising to some, but to support foreach in C# you don’t need to implement IEnumerable! All you have to do is:

Provide a public method GetEnumerator that takes no parameters and returns a type that has two members: a) a method MoveMext that takes no parameters and return a Boolean, and b) a property Current with a getter that returns an Object.

For example, the following type supports foreach:

 

class Foo {

    public Bar GetEnumerator() { return new Bar(); }

 

    public struct Bar {

        public bool MoveNext() {

            return false;

        }

        public object Current {

            get { return null; }

        }

    }

}

 

// the following complies just fine:

Foo f = new Foo();

foreach (object o in f) {

    Console.WriteLine(“Hi!”);

}

But, as you can see in the yellow highlight above, the describing the foreach pattern in English (or any other spoken language) is quite difficult and not very readable, especially if you contrast it with the simplicity specifying requirements based on static typing:

Implement IEnumerable.

… and having IEnumerable defined as:

public interface IEnumerable {

public IEnumerator GetEnumerator();

}

public interface IEnumerator {

public bool MoveMext();

public object Current { get; }

}

The english description gets much worse for something like the query pattern, which is way more complex than the foreach pattern. Because of that, I was thinking that there must be a better way to specify such patterns based on duck typing. But when I searched the web, to my surprise, I could not find any simple notations to do that. If you know of any, please let me know.

In the absence of an existing notation, I started to think about something like the following:

 

[Foreachable] {

    public [Enumerator] GetEnumerator();

}

[Enumerator] {

    public bool MoveMext();

    public [ItemType] Current { get; }

}

This seems much easier to parse than the English description of the pattern. What do you think?