Optional arguments on both ends

Optional arguments on both ends

Rate This
  • Comments 23

Before we get into today's topic, a quick update on my posting from last year about Roslyn jobs. We have gotten a lot of good leads and made some hires but we still have positions open, both on the Roslyn team and on the larger Visual Studio team. For details, see this post on the Visual Studio blog. Again, please do not send me resumes directly; send them via the usual career site. Thanks!


Here's a recent question I got from a reader: what is the correct analysis of this little problem involving optional arguments?

static void F(string ham, object jam = null) { }
static void F(string spam, string ham, object jam = null) { }
...
F("meat product", null);

The developer of this odd code is apparently attempting to make optional parameters on both ends; the intention is that both spam and jam are optional, but ham is always required.

Which overload does the compiler pick, and why? See if you can figure it out for yourself.

.

.

.

.

.

.

.

.

.

.

.

.

.

The second overload is chosen. (Were you surprised?)

The reason why is straightforward. The overload resolution algorithm has two candidates and must pick which is the best one on the basis of the conversions from the arguments to the formal parameter types. Look at the first argument. Either it is converted to string, or to... string. Hmph. We can conclude nothing from this argument, so we ignore it.

Now consider the second argument. We either convert null to object, if we pick the first overload, or to string, if we pick the second overload. String is obviously more specific than object; every string is an object, but not every object is a string. We strive to pick the overload that is more specific, so we choose the second overload, and call

F("meat product", null, null);

The moral of the story is, as I have said so many times, if it hurts when you do that then don't do that! Don't try to put an optional argument on both the front and back ends; it's just confusing as all heck, particularly if the types collide as they do here. Write the code as a single method with each optional parameter declaration coming at the end:

static void F(string ham, string spam = null, object jam = null) { }

With only one overload it is clear what argument corresponds to what parameter.

Now perhaps you see why we were so reticent to add optional arguments to overload resolution for ten years; it makes the algorithm less intuitive in some cases.

 

  • Please add an option no-optional-parm to let us turn them off at the complier level.

  • Eric, MSDN has broken your blog! :(

    Your comments no longer stand out, and your tags have been largely zapped. Tell them to quit screwing around, some of us are trying to learn.

    *kicks Cat : Animal<Cat>*

  • Eric, please bring back your stylish look and feel!!

  • So I understand the madness optional arguments can lead to. But why disallow them for so long and yet allow goto statements?

  • Changing the subject. Did anyone noticed that the blog text color is no longer purple?? This must be some kind of the end of an era in this blog history

  • I've just seen that the purple text is back! So maybe the issue was fixed, or it was something wrong with my browser's cache

    A number of people reported to me that the purple text disappeared on Friday; many thanks. In fact, all of my customizations got turned off. Something was misconfigured in the blog settings; it is restored now. -- Eric

  • Just add a compile time warning for ambiguous situations like this.

    That doesn't help because the problem is that it is not ambiguous! If it were ambiguous then it would be an error, not a warning. The problem is that the unambiguous best choice is possibly not the one that the user intended. But it is always the case that overload resolution could be choosing the method that the user did not intend. We can't go putting a warning on every usage of overload resolution that could possibly be wrong, because that's all of them. And suppose we did add a warning; what is the developer supposed to do to eliminate the warning?

    The point of the article is that this is a bad way to design overloads; design your overloads to work well with the overload resolution algorithm so that developer's intuitions more clearly match the meaning of the code. - Eric

  • I tend to avoid overloading methods in a way that there is a set of parameter types that is compatible with several overloads which have different semantics. Unfortunately not everybody has the same opinion.

    ASP.net MVC is guilty of that in some places too.

    For example the rendering of a view as several overloads, in particular two with the same parameter count. With the only difference being that one takes a model as object, and the other takes some name as string. And once I was lazy and decided to use string as my model class...

Page 2 of 2 (23 items) 12