My previous entry on default arguments raised a few questions. I thought it’d be worth writing another short entry to make a few things clearer.
The first thing is that default arguments could certainly have been implemented by overloads under the covers or in some other way that was version resillient. However, the CLR supports default arguments natively because: a) they were already a fundamental part of C++ and VB and b) they were already a fundamental part of COM. Rather than imposing a lot of overhead on the interop layer and the two languages, it seemed best to just implement default arguments as default arguments (especially since they’re only a tiny bit of extra metadata as far as the CLR is concerned). And, as I said in my first entry, not everyone agrees on the seriousness of the versioning question in the first place.
James Slaughter is right in that default arguments certainly introduce some interesting dilemmas for languages that support overriding and delegates. We had to work through those questions in the VS 2002 timeframe, but by taking a pretty conservative stand (I believe we just require you to restate the defaults exactly), I think it ends up being pretty clear and usable. I’m not sure how C++ approaches the problem, though.
Brad asks (more or less) “If all languages supported default arguments, then when would you use one over the other?” I think the answer, like so many class library questions, boils down to questions of aesthetics which are never easy to quantify. As I touched on in my original entry, I think in most cases overloads make a lot of sense. But there are some places where default arguments can make more sense. The best example I can think of is a Print method that optionally prints a newline. The BCL deals with this issue by creating two names, Print and PrintLine:
Sub Print(ByVal Value As Object)
Sub PrintLine(ByVal Value As Object)
This is an entirely valid way to deal with the situation. But in practice, you could also use default arguments to elegantly finesse the situation:
Sub Print(ByVal Value As Object, Optional ByVal NewLine As Boolean = True)
I’ve found myself doing this in the past when working on the compiler because it’s an easy way to extend a well-established method without having to create a whole new name.
Anyway, the point isn’t so much that default arguments are perfect, just that they can be useful in situations. I think one could come up with good design guidelines to allow choosing between the two, and maybe someday I’ll sit down and try to dream them up. Until then, we’ll all just have to muddle along…