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.
Comments
Post a Comment