Optional Arguments
The first new feature allows default arguments to be specified in a method signature. Callers of methods defined with default values can omit those arguments without having to define a specific overload matching that lesser argument list for convenience.
To define a default value in a method signature, you simply define a constant expression as the default value to use when omitted, similar to member initialize and constant definitions, except with some additional restrictions and rules. A simple example method definition that has one mandatory argument (p1, just like normal) and an optional argument definition (p2) takes the following form:
public void M ( int p1, int p2 = 5 );
The following invocations of method M are legal (will compile) and are functionally equivalent as far as the compiler is concerned:
M( 1, 5 );M( 1 ); // the declared default for p2 (5) is used
The rules when defining a method signature that uses optional parameters are
Valid optional argument definitions take the following form:
public void M1(string s, int i = 1) { }public void M2(Point p = new Point()) { }public void M3(Point p = default(Point)) { }public void M4(int i = 1, params string[] values) { }
The following method definitions using optional arguments will not compile:
//"Optional parameters must appear after all required parameters"public void M1 (int i = 1, string s) {}//"Default parameter value for 'p' must be a compile-time constant"//(Can't use a constructor that has parameters)public void M2(Point p = new Point(0,0)) {}//"Default parameter value for 'p' must be a compile-time constant"//(Must be a value type (struct or built-in value types only))public void M5(StringBuilder p = new StringBuilder()) {}//"A ref or out parameter cannot have a default value"public void M6(int i = 1, out string s = "") {}//"Cannot specify a default value for a parameter array"public void M7(int i = 1, params string[] values = "test") {}
To understand how optional arguments reduce our code, Listing 8-1 shows a traditional overloaded method pattern and the equivalent optional parameter code.
Listing 8-1: Traditional cascaded method overloads is a common pattern to handle default values. Using optional arguments simplifies this pattern and makes the default discoverable in the method signature, rather than in the code body itself.
public class OldWay{ // multiple overloads call the one master // implementation of a method that handles all inputs public void DoSomething(string formatString) { // passing 0 as param1 default, // and true as param2 default. DoSomething(formatString, 0, true); } public void DoSomething(string formatString, int param1) { DoSomething(formatString, param1, true); } public void DoSomething(string formatString, bool param2) { DoSomething(formatString, 0, param2); } // the actual implementation. All variations call this // method to implement the methods function. public void DoSomething( string formatString, int param1, bool param2) { Console.WriteLine( String.Format(formatString, param1, param2)); }}public class NewWay{ // optional parameters have a default specified. // optional parameters must come after normal params. public void DoSomething( string formatString, int param1 = 0, bool param2 = true) { Console.WriteLine( String.Format(formatString, param1, param2)); }}