tags:

views:

1669

answers:

9

Is it true that the only way to handle default function arguments is through function overloading?

For example, in PHP I can do this:

function foo($x, $y=0)
{
}

Would the best way to handle it in C# be this?

void foo(int x)
{
  foo(x, 0);
}

void foo(int x, int y)
{
}

Example lifted from here

Edit

Made the C# example into actual C# (Thanks Blair Conrad)

+4  A: 

Yes, that'd be best, except you'd omit the $s on the parameter names, as others have pointed out. For those interested in the rationale behind the lack of default parameter values, see @Giovanni Galbo's explanation.

Blair Conrad
+1  A: 

Default arguments are part of C++, but as of C# 3.5 default arguments are still not supported-- you'll have to overload. They've been available in VB.Net since 1.0.

Joel Coehoorn
A: 

Yes.

Or currying.

Or abstracting into a class and using default values there.

Unsliced
A: 

No, AFAIK C# does not support overriding, and yes, that is the recommended way of accomplishing the same effect.

Brian Stewart
A: 

Thank you all. I'm giving it to Blair since he answered first and all of the answers are pretty similar.

Mark Biek
+16  A: 

Just to satisfy some curiosity:

From Why doesn't C# support default parameters?:

In languages such as C++, a default value can be included as part of the method declaration:

void Process(Employee employee, bool bonus = false)

This method can be called either with:

a.Process(employee, true);

or

a.Process(employee);

in the second case, the parameter bonus is set to false.

C# doesn't have this feature.

One reason we don't have this feature is related to a specific implementation of the feature. In the C++ world, when the user writes:

a.Process(employee);

the compiler generates

a.process(employee, false);

In other words, the compiler takes the default value that is specified in the method prototype and puts it into the method call - it's just as if the user wrote 'false' as the second parameter. There's no way to change that default value without forcing the user of the class to recompile, which is unfortunate.

The overloading model works better in this respect. The framework author just defines two separate methods, and the single-parameter one calls the two-parameter method. This keeps the default value in the framework, where it can be modified if necessary.

It would be possible for a compiler to take something like the C++ definition and produce the overloads, but there are a few issues with that approach.

The first one is that the correlation between the code that the user writes and the code the compiler generates is less obvious. We generally try to limit magic when possible, as it makes it harder for programmers. The second issue has to do with things like XML doc comments and intellisense. The compiler would have to have special rules for how it generates doc comments for the overloaded methods, and intellisense would need to have smarts to collapse the overloaded methods into a single method.

Writing overloads yourself is a bit less convenient, but we think it's an acceptable solution.

Giovanni Galbo
+2  A: 

Regarding the excerpt from the csharp faq:

Most of the problems listed there were solved for VB.Net (specifically the intellisense and xml comments issues), meaning they're really red herrings-- there is code available to the C# team that will solve the problem.

Another reason has to do with forcing a user of a class to re-compile, but that's a bit of a red herring, too. If you change a default value in your framework class and the user does not have to recompile, you risk the user not knowing that the default value changed. Now you have a potential bug in the code that doesn't show up until runtime. In other words, the alternative of overloading the function is at least as bad. Of course, this also presumes a specific implementation of the feature, but it's the implementation suggested in the faq.

Therefore you have to weigh the remaining reason ("try to limit the magic") vs the fact (which they acknowledge) that writing the overloads is "a bit less convenient". Personally, I say put the feature in, and let the programmer decide whether or not to use it.

Joel Coehoorn
A: 

doe this not do the job?

void foo(int x):this(x, 0){}

void foo(int x, int y){ // code here }

gazhay
A: 

As pointed out, this isn't currently available in C# however they will be present within C# 4.0 as Sam Ng discusses on his blog:

http://blogs.msdn.com/samng/archive/2009/02/03/named-arguments-optional-arguments-and-default-values.aspx

Ian