Introduction
One of the very few things I missed in C++ when I was learning Java, is the default parameter feature. I had been hoping C# would bring back this feature. Unfortunately, I was told there is no default parameter feature in C#, the day I started learning C#. I was like, OK, we can live without default parameters. However, I just couldn't get default parameters out of my head, during the past years of writing C# programs. From time to time, I encountered situations where default parameters would have saved time and probably improved performance as well. So, here I am hacking my way into some brilliant/clumsy solution to it.
Background
The idea is simple if you have heard of the terms "parameter array" or "variable arguments", or the "params
" keyword. The "params
" keyword of C#, allows you to specify a variable number of parameters for a method. I guess 99% percent of people who write C# code have used the parameter array, because our very good friend Console.WriteLine(...)
itself can take variable number of arguments. And if you want to write your own method that takes a parameter array, you use the "params
" keyword. It works like this:
void PrintNumbers(params int[] numbers)
{
Console.WriteLine("Count: {0}", numbers.Length);
foreach (int n in numbers)
{
System.Console.WriteLine(numbers);
}
}
void Test()
{
PrintNumbers();
PrintNumbers(1);
PrintNumbers(2, 3);
PrintNumbers(4, 5, 6);
PrintNumbers(7, 8, 9, 10);
}
Now, a parameter array means any number of parameters (0 or more), and a default parameter means 0 or 1 parameter. Well, it's too obvious that default parameter is just a special case of a parameter array.
Implementation
Now, let us use the "params
" keyword and get the default parameter.
class DefaultParameterTest
{
private const int DEFAULT_ARG = 0;
void TakeDefaultArgument(int fixedArg, params int[] defaultArg)
{
if (defaultArg.Length > 1)
throw new ArgumentException("Too many arguments");
int defaultArgValue;
if (defaultArg.Length == 0)
defaultArgValue = DEFAULT_ARG;
else
defaultArgValue = defaultArg[0];
}
void Test()
{
TakeDefaultArgument(9);
TakeDefaultArgument(9, 0);
TakeDefaultArgument(9, new int[] { 0 });
TakeDefaultArgument(9, "0");
TakeDefaultArgument(9, 0, 1);
}
}
I used int
for illustration, but basically the default parameter can be any type.
Points of interest
There are many limitations and drawbacks of this workaround. (Otherwise it wouldn't be called a "workaround" anyway). Here are some of those:
The number of "defaultable" parameters is limited to only one, and it must be at the end of the parameter list.
The default parameter is type safe. But it gets quite tricky when the type of your default parameter itself is an array. (Probably more discussion on this later.)
If too many arguments are passed in, there are no compilation errors, not even warnings. Exception will be thrown at runtime. This is painful, because error checking is moved from compilation time to runtime, which is less efficient and more dangerous.
You can pass in an array of one element and it still works, though the method is expecting 0 or 1 element as an argument. This is because the C# parameter array can take not just single or multiple arguments, but also take a single array of arguments.
You cannot see the default value in the method's signature. The best solution I can think of is putting the default value in your XML style comments in an obvious way.
So a word of caution: if you ever want to use default parameters like this, document your method very carefully to make sure everybody else using this method knows exactly what's going on.
History
- 11 Oct 2006 - First draft.