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

One of the best uses I’ve seen so far for named arguments is to improve readability. Here’s an example of code that has poor readability.

Update(
  0.1,
  2.4,
  1.7,
  0.0,
  10.3,
  2.3,
  1.0,
  0.0,
  0.0);

I’m sure we’ve all seen something similar to this. What the heck are those values supposed to mean. Using comments for every value would help, but another solution is to name each argument.

Update(
  positionX: 0.1,
  positionY: 2.4,
  positionZ: 1.7,
  velocityX: 0.0,
  velocityY: 10.3,
  velocityZ: 2.3,
  accelerationX: 1.0,
  accelerationY: 0.0,
  accelerationZ: 0.0);

This is much more readable. We can see clearly that this Update function is used for some physical properties of an object and we can clearly see where each value is being applied.

That does it for this tutorial on optional and named arguments. Hopefully you can see where this syntax would be useful in your own systems and you begin using them to create higher quality code. If you’ve got any questions or comments, please leave them below.

Leave a Reply

Your email address will not be published. Required fields are marked *