Monthly Archives: December 2003

Default arguments are not perfect

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…

Why not ++ and –?

One question we occasionally get is why we didn’t introduce C-style increment (++) and decrement (–) operators into the language when we introduced the compound operators (i.e. += and -=). We did consider it, but:

  1. Assignment in VB is always done at the statement level and not the expression level. Introducing a ++ statement and — statement seemed pretty redundant. If you’re going to have “x++” as a statement, why not just use “x += 1”?
  2. If we introduced ++ and — as assignment expressions, then it would be weird not to allow general assignment expressions. For example, in C#, you can say “if ((x = foo()) == 10) {}” and have the assignment done as part of evaluating the if expression. The problem, as you might have already guessed, is that we already use the = operator in expressions for testing value equality. Thus, there would be no easy way to introduce general assignment expressions into the language, which would make it strange that we had — and ++.
  3. Even if we ignored the weirdnesses inherent in having increment and decrement with no assignment, the operators’ main function in C often times seems to be to encourage programmers to write arcane and brittle code. Besides the confusion in meaning between prefix and postfix, the increment/decrement operators usually depend on the order of evaluation of expressions. Which requires remembering the order of evaluation in a particular language, which isn’t always very obvious. For example, in C, what do the following expressions result in? It really depends on the order in which the expressions happen to be evaluated.
a[b++] = b
a[b] = ++b
foo(b++, ++b, b++, ++b)

Overall, we felt we were better off just leaving the increment and decrement operators alone.