C# 4.0 is coming soon and as usual brings some syntactic sugar along to make our programmers lives a little happier. One of the new features is named and optional parameters.
Optional parameters
The optional parameters feature is not new in other languages. VB 4.0 had it already in similar form so you could declare something like:
Public Sub MyMethod (Optional MyParameter as Variant) EndSub
C++ also had this feature for a while:
void MyMethod(string msg, bool isTrue = true)
{
//...
}
What is the purpose of optional parameters? Optional parameters are useful to replace overloading. Often by overloading methods, we would do several version of a method just to call some other version with passing some default parameter, like for example:
public class MyClass
{
public static void SomeMethod(string str, bool isTrue)
{
// This method does the actual work
}
public static void SomeMethod(string str)
{
MyMethod(str, <strong>true</strong>);
}
}
With optional parameters this is not necessary, because we can declare the isTrue parameter as optional and have only one method:
public static void SomeMethod(string str, bool isTrue = true)
{
// Do the work
}
The syntax for this is to follow the parameter name with “=” and provide the default value (like in C++).
There are of course some limitations. For example, what is going to happen if we say following:
public static void SomeMethod(string str="Default" , bool isTrue )
{
// Do the work
}
Sorry, this won’t compile, because optional parameters must appear after all required parameters.
The first thing I tried and got disappointed in a way, was the initialization of a custom type. For example:
// This won't compile!!!
public static void MyMethod(string stringParameter = "[Default]",
bool isTrue=true,
CustomClass myType=
new CustomClass("Created as optional parameter"))
{
Console.WriteLine(stringParameter);
Console.WriteLine(isTrue);
Console.WriteLine(myType);
}
Nope, this is not gonna compile.
Default parameter value for ‘myType’ must be a compile-time constant.
The default value must be known at compile time.
OK, now the time is for the full truth. It was possible to declare optional parameters in C# prior version 4.0, by putting a [Optional] attribute (System.Runtime.InteropServices) and a [DefaultParameter] attribute, but it was not possible to invoke it in optional manner from a C# application. Here is an example:
public static void MyMethod(
[Optional]
[DefaultParameterValue("[First Default]")]string firstStringParameter,
[Optional]
[DefaultParameterValue("[Second Default]")]string secondStringParameter,
[Optional]
[DefaultParameterValue(true)]bool isTrue)
{
Console.WriteLine(firstStringParameter);
Console.WriteLine(secondStringParameter);
Console.WriteLine(isTrue);
}
or in C# 4.0 fashion
public static void MyMethod(string firstStringParameter = "[First Default]",
string secondStringParameter = "[Second Default]", bool isTrue = true)
{
Console.WriteLine(firstStringParameter);
Console.WriteLine(secondStringParameter);
Console.WriteLine(isTrue);
}
if we dissect the IL code we will notice that the output is the same for both approaches.
.method public hidebysig static void MyMethod(
[opt] string firstStringParameter,
[opt] string secondStringParameter,
[opt] bool isTrue) cil managed
{
.param [1] = "[First Default]"
.param [2] = "[Second Default]"
.param [3] = bool(true)
//...
} // end of method Program::MyMethod
Named parameters
Named parameters is a feature that allows to call a method and map the value being passed with a certain parameter. As you can imagine this allows you to pass the parameters in any order you like. The syntax is simple, just name the parameter you would like to initialize and suffix it with “:” and then provide a value:
int sum = Sum(parameterOne: 7, parameterTwo: 5);
// public int Sum(int parameterOne, int parameterTwo){ }
or you can turn them around, so they don’t have to match the order in the method signature:
int sum = Sum(parameterTwo: 5, parameterOne: 7);
For example if we take the MyMethod with optional parameters from the previous example, we can demonstrate the named parameters. For example if we call the method in this way:
MyMethod( "Don't take the default one on first parameter");
the output would be:
Don't take the default one on first parameter [Second Default] True
As you can see the parameters are optional, and the firstStringParameter will be replaced with an actual value. If we call MyMethod in the following way, we can say “Call MyMethod and pass to secondStringParameter the following string”:
MyMethod(secondStringParameter: "The second one should not be default");
[First Default]
The second one should not be default
True
As you can see, even if we passed only one parameter the second, we pass it to secondStringParameter
This feature comes handy when interacting with COM types that have large signatures, mostly with optional parameters. Beside this it improves the readability of the code.