Named and optional parameters are really two distinct
features, but are often useful together. Optional parameters allow you to omit
arguments to member invocations, whereas named arguments is a way to provide an
argument using the name of the corresponding parameter instead of relying on
its position in the parameter list.
Some APIs, most notably COM interfaces such as the Office
automation APIs, are written specifically with named and optional parameters in
mind. Up until now it has been very painful to call into these APIs from C#,
with sometimes as many as thirty arguments having to be explicitly passed, most
of which have reasonable default values and could be omitted.
Even in APIs for .NET however you sometimes find yourself
compelled to write many overloads of a method with different combinations of
parameters, in order to provide maximum usability to the callers. Optional
parameters are a useful alternative for these situations.
Optional parameters
A parameter is declared optional simply by providing a
default value for it:
public void M(int x, int y = 5, int z = 7);
Here y and z are optional parameters and can be omitted in
calls:
M(1, 2, 3); // ordinary call of M
M(1, 2); // omitting z โ equivalent to M(1, 2, 7)
M(1); // omitting both y and z โ equivalent to M(1, 5, 7)
Named and optional arguments
C# 4.0 does not permit you to omit arguments between commas
as in M(1,,3). This could lead to highly
unreadable comma-counting code. Instead any argument can be passed by name.
Thus if you want to omit only y from a call
of M you can write:
M(1, z: 3); // passing z by name
or
M(x: 1, z: 3); // passing both x and z by name
or even
M(z: 3, x: 1); // reversing the order of arguments
All forms are equivalent, except that arguments are always
evaluated in the order they appear, so in the last example the 3 is evaluated before the 1.
Optional and named arguments can be used not only with
methods but also with indexers and constructors.
Overload resolution
Named and optional arguments affect overload resolution, but
the changes are relatively simple:
A signature is applicable
if all its parameters are either optional or have exactly one corresponding
argument (by name or position) in the call which is convertible to the
parameter type.
Betterness rules on conversions are only applied for
arguments that are explicitly given โ omitted optional arguments are ignored
for betterness purposes.
If two signatures are equally good, one that does not omit
optional parameters is preferred.
M(string s, int i = 1);
M(object o);
M(int i, string s = "Hello");
M(int i);
M(5);
Given these overloads, we can see the working of the rules
above. M(string,int) is not applicable because 5 doesn't convert to string.
M(int,string) is applicable because its second
parameter is optional, and so, obviously are M(object)
and M(int).
M(int,string) and M(int) are both better than M(object) because the conversion from 5 to int
is better than the conversion from 5
to object.
Finally M(int) is
better than M(int,string) because no optional
arguments are omitted.
Thus the method that gets called is M(int).
Downlaod complete features list here:
http://code.msdn.microsoft.com/csharpfuture/Release/ProjectReleases.aspx?ReleaseId=1686