Sunday, June 05, 2011

C# Tutorial - Optional and Named Arguments

When C# 4.0 was released, developers got their hands on some syntactic sugar that helps in the readability and maintainability of code - optional arguments and named arguments.
Optional Arguments
The first concept we'll be looking at today is optional arguments. Let's use optional arguments to help a common maintainability issue - adding another argument to a function. Here's a really basic method that we'll be extending.

public void MyFunction(int a)
{
  Console.WriteLine("Parameter a is: {0}", a);
}

...

MyFunction(3);

// Output: Parameter a is: 3
At some point in the future, as often happens, a developer decides MyFunction needs to do a little more and needs another argument.
public void MyFunction(int a, int b)
{
  Console.WriteLine(a);
  Console.WriteLine(b);
}

This introduces a maintainability problem - everywhere that MyFunction is called now needs to supply another argument. What the developer can do instead is assign argument "b" a default value.

public void MyFunction(int a, int b = 4)
{
  Console.WriteLine("Parameter a is: {0}", a);
  Console.WriteLine("Parameter b is: {0}", b);
}
...

MyFunction(3);
// Output: Parameter a is: 3
// Output: Parameter b is: 4

With the use of optional parameters none of the calling code needs to change, and the developer can be at least a little more confident that she didn't break existing code.
There's no limit to the types that can be used in optional parameters. Let's extend our method again by adding an optional string parameter.

public void MyFunction(int a, int b = 4, string c = "foo")
{
  Console.WriteLine("Parameter a is: {0}", a);
  Console.WriteLine("Parameter b is: {0}", b);
  Console.WriteLine("Parameter c is: {0}", c);
}

This function can now be called three different ways.

MyFunction(3);

// Output: Parameter a is: 3
// Output: Parameter b is: 4
// Output: Parameter c is: foo
MyFunction(3, 5);
// Output: Parameter a is: 3
// Output: Parameter b is: 5
// Output: Parameter c is: foo
MyFunction(3, 5, "bar");
// Output: Parameter a is: 3
// Output: Parameter b is: 5
// Output: Parameter c is: bar
So now what happens if a caller wants to use MyFunction and only supply values for "a" and "c". This is now possible with the use of named arguments.


Named Arguments
Using named parameters, let's call the previous function and supply values for "a" and "c".
MyFunction(3, c: "bar");
// Output: Parameter a is: 3
// Output: Parameter b is: 4
// Output: Parameter c is: bar
As you can see, named arguments are used by supplying the name of the argument, a colon, and then the value you'd like to supply for that argument. If you don't supply a name, like I did in this case, they will be assigned in the order they appear in the method signature.
We could also reorder the arguments, if we wanted.
MyFunction(c: "bar", a: 3);
// Output: Parameter a is: 3
// Output: Parameter b is: 4
// Output: Parameter c is: bar

Read more: Switch on code