C# Adds Optional and Named ArgumentsBy Scott Mitchell
Earlier this month Microsoft released Visual Studio 2010, the .NET Framework 4.0 (which includes ASP.NET 4.0), and new versions of their core programming languages: C# 4.0 and Visual Basic 10. In designing the latest versions of C# and VB, Microsoft has worked to bring the two languages into closer parity. Certain features available in C# were missing in VB, and vice-a-versa. Last week I wrote about Visual Basic 2010's language enhancements, which include implicit line continuation, auto-implemented properties, and collection initializers - three useful features that were available in previous versions of C#. Similarly, C# 4.0 introduces new features to the C# programming language that were available in earlier versions of Visual Basic, namely optional arguments and named arguments.
Optional arguments allow developers to specify default values for one or more arguments to a method. When calling such a method, these optional arguments may be omitted, in which case their default value is used. In a nutshell, optional arguments allow for a more terse syntax for method overloading. Named arguments, on the other hand, improve readability by allowing developers to indicate the name of an argument (along with its value) when calling a method. This article examines how to use optional arguments and named arguments in C# 4.0. Read on to learn more!
Consider a class that sends an email message. This class might have a method named
Sendthat accepts string arguments specifying the important parts of the email message: the sender, the recipient(s), the subject, the body, the CC recipients, the BCC recipients, and so forth. While some of these inputs are required - the sender, the recipient(s), the subject, and the body - others, like the CC and BCC recipients, are clearly optional. How would you design the
Sendmethod to accept these arguments? One approach would be to create a single method that defines all of the arguments:
While this would certainly work, developers using this code would always need to supply values for the
bccRecipients arguments, even
for emails that had no CC or BCC recipients (presumably, they'd pass in a
Another approach is to use method overloading. With method overloading you can define multiple signatures for a single method. So we could define one signature that
accepts just the four required inputs; another that accepts the four required input plus the CC recipients; and a third that accepts all six inputs. The first two methods -
the ones that accept fewer than six arguments - would simply call the
Send overload that supported all six, passing in
null for those
argument values not provided.
With method overloading, the developer using this class can call the appropriate overload. If she wants to send an email without CC or BCC recipients, she can use the one that accepts just four arguments. To include CC recipients, she'd use the one that accepts five arguments. Method overloading offers a great deal of flexibility, as each method overload can have entirely different arguments and can implement their logic in unique ways. However, using method overloading to simply suppress specifying additional arguments increases the volume of code needed the class.
A third option, which offers improved readability and terseness for both the class designer and the developers using it, is to use optional arguments. Using optional arguments we get the best of both worlds: the developer designing the class can define the method using just one signature (rather than having to use multiple overloads) and the developer calling the class's method can supply only those arguments of interest, much like when using method overloading. To indicate that a method's argument is optional, specify its default value in the method signature.
Returning to the
Send method example, to indicate that the
bccRecipients arguments are optional and that, if not specified,
their value should be
null, use the following sytnax:
With optional arguments, the class only needs one
Send method defined. A developer using this class can call the method with or without the optional arguments.
And when writing the code to call the
Send method, Visual Studio's IntelliSense shows the optional arguments (and their default values) in brackets.
The following uses of the
Send method are all valid:
There are a couple of things to keep in mind when using optional arguments. First, any optional arguments must come after the required arguments in the method signature. For example, the following method signature is invalid because a required argument comes after an optional arguments:
Second, the default value specified for an optional arguments must be a compile-time constant, such as
3, "Hello, World", or
DateTime.Now are not permitted.
Finally, when calling a method with optional arguments you cannot omit an optional argument value if you specify an optional argument value to the right of it. Returning
to our example, we could not omit the
ccRecipients argument value while providing the
bccRecipients value when calling the
When writing the code to call a method, Visual Studio's IntelliSense helpfully shows the names and types of the various arguments. When looking back at the code hours, days, or weeks later, you might not remember the meaning of the arguments. Returning to our earlier example, when writing the code to call the
Sendmethod it is clear that the first string argument specifies the sender, the second the recipient(s), and so on. But when returning to the code sometime later it's not as clear. Consider the following method call:
Who is the email being sent from? Scott, Alice, Jisun, or Sam? And who is receiving the email, who is being CCed, and who is being BCCed? If you had recently used the
Send method (or used it quite often) you'd likely know off the top of your head, but if it had been a while since you last used this method (or if you were
reviewing someone else's code and had never used the
Send method) you might be at a loss as to who was sending the email, who was receiving it, and who was being
CCed and BCCed.
Named arguments can help clear up any confusion. Named arguments allow the developer calling the method to precede a argument's value with its name using the following syntax. (Note: the line breaks and spacing here is to enhance readability and is not required.)
That's much more readable, I think you'd agree. Now there would be no confusion as to the sender, recipient, CC, and BCC values. What's more, when using named arguments the
order of the named arguments does not necessarily have to match the order of the arguments as defined in the method's signature. For example, the following call to
Send is valid:
bccRecipients argument has been omitted (as it is an optional argument) and the arguments have been reordered so that the recipient(s) is specified
first, then the sender, and then the CC recipient(s), followed by the subject and body. In fact, when using named arguments you can omit any optional arguments, regardless
of their position relative to one another. That is, using named arguments you could call Send specifying a value for
bccRecipients but omitting a value for
ccRecipients, something that is not possible when using positional arguments (due to the fact that in the method signature
ccRecipients is defined
Finally, note that you can mix named and positional arguments. However, in doing so the named arguments must follow all of the positional ones. The following code shows some examples of valid and invalid calls using positional and named arguments:
Microsoft has worked hard to better align Visual Basic and C# in this latest release. A number of features that were once the sole domain of C# have been added to VB. And as we saw in this article, a number of VB features have been added to C#, namely optional and named arguments.