Virtual Developer Workshop: Containerized Development with Docker
When you create a public method that will be frequently used by a variety of different clients in many different contexts, it is best to provide as much flexibility in the ways your method can be called as possible. Specifically, some clients may wish to call your method using only a single argument or no argument at all and go with all the standard defaults. Other clients might want more control and wish to pass many arguments to specify all the details about how your method should work. To satisfy the needs of both of these clients (and all the ones in-between), you need to anticipate and try to accommodate all valid options.
The Visual Basic .NET language has three different approaches for specifying optional parameters. Each has its benefits and drawbacks. This tip discusses each to help you pick the right approach for your methods.
The Optional Keyword
If you're long in the tooth and have been a VB developer since before the .NET suffix was added to the name, then the first answer that pops into your head for addressing this situation probably is the Optiona/ keyword. Optional can be specified for parameters when creating a subroutine or function to indicate that passing the argument is not necessary. This is simple and straightforward. The only real limitation is that the optional parameters have to come at the end of your parameter list.
However, the Optional keyword has a downside. Although it is supported by VB .NET and is technically CLR-compliant, it is not supported or understood in C#. So why should a dyed-in-the-wool VB developer care about that? If you are creating only a private method that will be called from your own code, then you probably shouldn't. However, if you want to make this class publicly available to call from other applications, then you have to allow for the fact that some of those other applications may be written in other languages. And while the .NET Framework has made multi-language development easy, it still has the occasional bumps and this is one of them: a C# application that calls your method will always be required to pass all the arguments specified. So much for flexibility!
Fortunately, there are other options that are more C#-friendly.
Overloading is the process of creating several methods within a single class. The methods all have the exact same name, but they accept different arguments. Whenever that method is called, the arguments passed are evaluated and the method that has matching parameters is the one that gets called.
This means that you could create a method named MyFunction that accepts five arguments and then does all the appropriate processing with those arguments and returns the result. You could then create another method, also called MyFunction, that has only the first four arguments. In this MyFunction, you'd simply supply a default value for the fifth argument and then call the five-argument version of MyFunction to do the actual work. Likewise for a three-, two-, one- and zero-argument version of MyFunction.
While this does require you to create five functions rather than just one, all but one of the functions are trivial, simply setting default values and calling the MyFunction that does the real work. This is called overloaded method chaining.
What are the benefits of this approach? It is fully supported by C# and probably every other .NET language out there.
In addition, overloading allows you to do much more than simply make some arguments optional. You can create two different MyFunction methods, where both accept only one argument. They are distinguished by the type of the argument. So if MyFunction is designed to return an item from a data structure, you could have a MyFunction that accepts a string and then does a search for the first item with a matching string. Whereas the MyFunction that accepts an integer could use the number as an index into the data structure and return the corresponding item. This capability means you can provide even more flexibility in what your method will accept and how it will respond to it.
Last But Not Least, ParamArray
The third option to consider when thinking about providing a method with optional arguments is ParamArray. ParamArray allows the calling routine to pass as many or as few arguments as it wants. Your method receives these arguments in an array and can then walk through the array and process whatever was passed.
Good programming practice suggests that you should always have a specific data type for your arrays, so this approach is limited to situations where all the arguments are of the same data type. (Yes, you could create a ParamArray of type Object that accepted values of different data types for each argument, but this would be poor programming practice and would require a lot of type validation and conversion code in your method.)
Although ParamArray is limited to a single data type, it does make it possible to accept as many arguments as the caller wants to providea feat that can't be implemented using the Optional keyword or overloading. In addition, ParamArray works seamlessly with C# and other languages.