One of the new C# 4 features are optional and named parameters. After many years and many requests to these features we finally have it in C# 4. Named and optional parameters can be used completely independent of each other.
Named parameters can be used with any method that is invoked. This feature depends on the variable name and allows invoking the method by using the variable name in any order.
Let’s get into an example to invoke this Bar() method.
public void Bar(int x, int y)
{
Console.WriteLine("Bar(int, int) {0} {1}", x, y);
}
The Bar() method can be invoked in a traditional way passing two parameters,…
var t = new Test();
t.Bar(1, 2);
…and it can be invoked passing the names x and y, and assigning values to the variable names.
t.Bar(x: 3, y : 4);
It’s also possible to assign positional parameters and named parameters. The positional parameters must come first. The last parameters can be named parameters. Of course, the positional parameters that already have been assigned may not be specified with a named parameter.
t.Bar(5, y: 6);
Using named parameters also allows changing the order passing the values. y can be assigned to before x.
t.Bar(y: 7, x: 8);
This way you can also do something like this:
int a = 7;
t.Bar(y: a++, x: a);
What would you expect is passed? The compiler changes the order to send x as the first parameter and y as the second. To fulfill the left-to-right ordering, a temporary variable is created, and 8 is passed with the first (x) and 7 with the second (y) parameter.
int tmp = a++;
t.Bar(a, tmp);
With named parameters the variable name is just used during compile time. Changing this name with the method definition the program still runs as the variable name is not used from the generated IL code. Of course, compiling the invocation of the method once more a compiler error occurs.
Optional parameters must be defined with the method definition. The default values for optional parameters are assigned in the method declaration like x and s in the first declaration of the Foo() method. Optional parameters must follow all required parameters. It’s possible to overload methods that have optional parameters with methods that do not have optional parameters. The C# compiler makes use of the attributes Optional and DefaultParameterValue that are added to the parameter declarations.
public void Foo(int x = -1, string s = "default")
{
Console.WriteLine("Foo(int, string) {0} {1}", x, s);
}
public void Foo(int x)
{
Console.WriteLine("Foo(int) {0}", x);
}
The method Foo can now be invoked without parameters. Here the compiler creates a call to invoke the Foo method with –1 and “default” parameter values. With the second version to call the Foo method, the second declaration of Foo has a better match with one required int parameter. The third call invokes the Foo method with 22 and “abc” parameter values.
t.Foo();
t.Foo(11);
t.Foo(22, "abc");
Of course it’s possible to combine named and optional parameters. Here, the first invocation of Foo invokes the Foo method with 2 and “default” values, the second invocation with –1 and “abc” values.
t.Foo(x : 2);
t.Foo(s: "abc");
What’s the reason we had to wait so long for the named and optional parameters as this feature exists for such a long time in other programming languages? The reason was versioning, and this is still an issue. If the default values of optional parameters change with a new version, and the calling code is not recompiled, the calling assembly still has the original version of the parameters. Because of this versioning issue the C# team was resistant to implement this feature – until C# 4. Of course optional parameters have big advantages in calling COM objects.
Don’t change the defaults of optional parameters unless you are aware that calling code is already compiled with the previous version of defaults.
More information on this in my new upcoming book Professional C# 4 with .NET 4.
- Christian