Developer

Handling optional parameters in C#

One feature that's missing from C# is the ability to declare a method parameter as optional. This article will show you how to fake it.


Q: I’m trying to figure out how to make a method parameter optional in C#. If you could help me figure this out, I’d appreciate it.

A: While most modern programming languages provide some way of declaring optional function parameters, C# doesn’t provide a way of directly doing so, despite the fact that VB.NET and .NET’s attribute system both support this functionality. This is a subject of some debate currently in the C# community. The C# development team’s position seems to boil down to the following: When provided, this feature is usually nothing more than dressing up method overloading with a little syntactic sugar.

When you get right down to it, their position makes some sense. A function with an optional parameter is in reality two different functions: one that assumes some default behavior if the optional parameter is omitted, and another that performs more specific behavior based on the value of the optional parameter if provided. But that doesn’t change the fact that using overloaded methods to provide optional parameter support feels a little clunky. It works, but you always wind up writing more code, and you pollute your object interface with the extra method signatures required to support all of your optional parameters. Let’s look at some alternatives.

Parameter arrays
If you take a look at the classes found in the common language runtime (CLR), you’ll find more than a few with methods that can accept a variable-length list of parameters. One example would be the System.Console.WriteLine method, which has an overloaded declaration that works to support replaceable parameters in the string written to the console. For example, this code:
Console.WriteLine("{0} jumped over {1}.", "The cow", "the moon");

produces the following output:
The cow jumped over the moon.

Any number of replaceable parameters can be specified in this fashion, which means that the number of arguments passed to the WriteLine method can vary from call to call. C# supports this behavior with the params keyword, which, when used before an array type in a function’s argument list, creates a parameter array. You can use this array to fake optional parameters in practice. Check out Listing A for an example of this in action.

You can see that this solution works pretty well. The OptionalStrings method may be legally called with no parameters, in which case the parameter array args is simply empty—in effect, the entire array is optional. Further, the calling function doesn’t need to explicitly wrap the parameters it sends in an array, and since the parameter array is an honest-to-goodness array, the called function can easily determine how many parameters it has received. But there are a few caveats:
  • ·        There’s no enforceable limit to the number of arguments received in this way. You couldn’t, for instance, declare the OptionalStrings method to receive a maximum of three optional arguments without writing code to do so at runtime inside the function itself.
  • ·        Similarly, there’s no way to make the array typesafe. If you need to support multiple types in the parameter array, you’re limited to using a lowest-common-denominator approach, usually declaring the parameter array as type Object.
  • ·        Only one parameter may be marked using params, and it must be the last parameter in the method’s argument list.
  • ·        You can't specify an optional out (passed by reference) parameter using this method.

An object-oriented solution
Another possible solution would be to create a class encapsulating all the possible arguments a method could receive, and pass an instance of that class to the method in question. This approach makes sense from an object-oriented point of view and solves the problems I pointed out with the parameter array solution, as you can see from Listing B.

By creating a default, parameterless constructor for the ParameterClass class, I can set whatever default values I want for the public fields, which represent the possible parameters for the OptionalObjects method. I just override any of the fields I’m interested in actually providing a value for, and pass the whole object to OptionalObjects. Because objects are passed by reference, any changes made to a ParameterClass field while inside the OptionalObjects method are reflected when the method returns. In effect, the whole object is an out parameter.

Not only does this provide a neat solution to the optional parameter conundrum, but passing arguments in the form of objects also serves to further insulate your classes from one another. It’s possible, using this method, to add additional arguments for OptionalObjects with a minimum of fuss. Simply redefining ParameterClass to contain the new fields is all that’s required.

Not perfect, but it works
None of these solutions is perfect, but they all enable you to fake your way into supporting optional parameters in your applications. Since the last word received from Microsoft seems to indicate that built-in optional parameter support will not be forthcoming, we’ll have to get by with workarounds like these.

 

 

Editor's Picks