Wednesday, May 11, 2011

Optional argument corner cases, part one

In C# 4.0 we added "optional arguments"; that is, you can state in the declaration of a method's parameter that if certain arguments are omitted, then constants can be substituted for them:

void M(int x = 123, int y = 456) { }

can be called as M(), M(0) and M(0, 1). The first two cases are treated as though you'd said M(123, 456) and M(0, 456) respectively.

This was a controversial feature for the design team, which had resisted adding this feature for almost ten years despite numerous requests for it and the example of similar features in languages like C++ and Visual Basic. Though obviously convenient, the convenience comes at a pretty high price of bizarre corner cases that the compiler team definitely needs to deal with, and customers occasionally run into by accident. I thought I might talk a bit about a few of those bizarre corner cases.
First off, a couple having to do with interfaces. Let's take a look at how optional arguments interact with "implicit" interface implementations.

interface IFoo 
  void M(int x = 123); 
}
class Foo : IFoo 
{
  public void M(int x){}
}
Here the method M is implicitly implemented by Foo's method M. What happens here?

Foo foo = new Foo();
foo.M();