C# 4 Named Parameters for Overload Resolution

Posted by Steve Michelotti on Geeks with Blogs See other posts from Geeks with Blogs or by Steve Michelotti
Published on Mon, 15 Mar 2010 22:14:02 GMT Indexed on 2010/03/16 5:16 UTC
Read the original article Hit count: 447

Filed under:

C# 4 is getting a new feature called named parameters. Although this is a stand-alone feature, it is often used in conjunction with optional parameters. Last week when I was giving a presentation on C# 4, I got a question on a scenario regarding overload resolution that I had not considered before which yielded interesting results. Before I describe the scenario, a little background first.

Named parameters is a well documented feature that works like this: suppose you have a method defined like this:

   1:  void DoWork(int num, string message = "Hello")
   2:  {
   3:      Console.WriteLine("Inside DoWork() - num: {0}, message: {1}", num, message);
   4:  }

This enables you to call the method with any of these:

   1:  DoWork(21);
   2:  DoWork(num: 21);
   3:  DoWork(21, "abc");
   4:  DoWork(num: 21, message: "abc");

and the corresponding results will be:

Inside DoWork() - num: 21, message: Hello
Inside DoWork() - num: 21, message: Hello
Inside DoWork() - num: 21, message: abc
Inside DoWork() - num: 21, message: abc

This is all pretty straight forward and well-documented. What is slightly more interesting is how resolution is handled with method overloads. Suppose we had a second overload for DoWork() that looked like this:

   1:  void DoWork(object num)
   2:  {
   3:      Console.WriteLine("Inside second overload: " + num);
   4:  }

The first rule applied for method overload resolution in this case is that it looks for the most strongly-type match first.  Hence, since the second overload has System.Object as the parameter rather than Int32, this second overload will never be called for any of the 4 method calls above.  But suppose the method overload looked like this:

   1:  void DoWork(int num)
   2:  {
   3:      Console.WriteLine("Inside second overload: " + num);
   4:  }

In this case, both overloads have the first parameter as Int32 so they both fulfill the first rule equally.  In this case the overload with the optional parameters will be ignored if the parameters are not specified. Therefore, the same 4 method calls from above would result in:

Inside second overload: 21
Inside second overload: 21
Inside DoWork() - num: 21, message: abc
Inside DoWork() - num: 21, message: abc

Even all this is pretty well documented. However, we can now consider the very interesting scenario I was presented with. The question was what happens if you change the parameter name in one of the overloads.  For example, what happens if you change the parameter *name* for the second overload like this:

   1:  void DoWork(int num2)
   2:  {
   3:      Console.WriteLine("Inside second overload: " + num2);
   4:  }

In this case, the first 2 method calls will yield *different* results:

   1:  DoWork(21);
   2:  DoWork(num: 21);

results in:

Inside second overload: 21
Inside DoWork() - num: 21, message: Hello

We know the first method call will go to the second overload because of normal method overload resolution rules which ignore the optional parameters.  But for the second call, even though all the same rules apply, the compiler will allow you to specify a named parameter which, in effect, overrides the typical rules and directs the call to the first overload. Keep in mind this would only work if the method overloads had different parameter names for the same types (which in itself is weird). But it is a situation I had not considered before and it is one in which you should be aware of the rules that the C# 4 compiler applies.

© Geeks with Blogs or respective owner