When writing functions in C♯ sometimes one ends up putting parameters that might not be required all the time or when omitted would like to place a default value to these parameters. The way this is tackled is by using method overloads with different parameters. However, from the release of .NET 4.0 it is possible to define a single function with optional parameters. Optional parameters are defined by providing a default value to the parameter. During compilation when a function call with the optional parameter missing is found the compiler will insert the default value for the parameter in order to match the function signature.
In the following test scenarios the compilation result between the function overloading and the use of optional parameters are presented.
Test Scenario 1:
Let’s consider a function that requires a string to be supplied with the option to supply an additional string. Doing this in the traditional way:
public static void TestTraditional(string parameter1)
{
TestTraditional(parameter1, "optional");
}
public static void TestTraditional(string parameter1, string parameter2)
{
Console.WriteLine(parameter1 + parameter2);
}
When calling these the function with 2 parameters the second function will be called. Otherwise if one parameter is supplied the first function is called.
TestTraditional("required");
TestTraditional("required", "optional but value required");
ldstr "required"
call void OptionalParameters.Program::TestTraditional(string)
ldstr "required"
ldstr "optional but value required"
call void OptionalParameters.Program::TestTraditional(string, string)
Test Scenario 2:
Now let’s modifying the second function to make use of optional parameters in a way to remove the need of defining two different functions.
public static void TestWithOptional(string parameter1, string parameter2 = "optional")
{
Console.WriteLine(parameter1 + parameter2);
}
The optional parameter changes slightly the function description generated by the compiler for the function.
.method public hidebysig static void TestWithOptional(string parameter1,
[opt] string parameter2) cil managed
{
.param [2] = "optional"
// Code size 13 (0xd)
.maxstack 8
ldarg.0
ldarg.1
call string [mscorlib]System.String::Concat(string, string)
call void [mscorlib]System.Console::WriteLine(string)
ret
}
This modification instructs the compiler that any call to the method needs to have the optional parameter inserted as can be seen in the MSIL code generated for the following C# statements.
TestWithOptional("required");
TestWithOptional("required", "optional");
TestWithOptional("required", "changed value");
ldstr "required"
ldstr "optional"
call void OptionalParameters.Program::TestWithOptional(string, string)
ldstr "required"
ldstr "optional"
call void OptionalParameters.Program::TestWithOptional(string, string)
ldstr "required"
ldstr "changed value"
call void OptionalParameters.Program::TestWithOptional(string, string)
Conclusion
The use of optional parameters simplifies the need for defining different methods. However if the function using the optional parameters reside into a library file and needs modification to the function signature one have to remember that the entire project code needs to be recompiled. The project recompilation is required as the default value of the optional parameter is not stored in the function but rather pushed on the stack before the function call is performed.