4

I have defined the following method:

void Write(string fileContent, string fileName, string container = StorageBlobContainers.ProfilePictures)

The code compiled with no problem, so I wrote the code to execute it (from a diffferent file):

string json = JsonConvert.SerializeXNode(node);
FileProcessor.Write(json, "productscontainer");

But it seemed like for some reason it just did nothing.
After a few minutes of struggling to understand the problem, I finally found it. Somewhere in the same class, there was already a Write function defined like this:

void Write(string filePath, string container = StorageBlobContainers.ProfilePictures)
{
  if (!File.Exists(filePath))
    return string.Empty;
  ...

This really confused me, as it did compile fine, and of course, it makes sense as one method has 3 parameter signature and the other one has 2, but isn't this very ambiguous and/or error prone? For me it seems like none of the methods are the "logical" one to choose. Why is the 2nd one chosen over the other?

iuliu.net
  • 6,666
  • 6
  • 46
  • 69
  • "Why is the 2nd one chosen over the other?" - because those are the rules of the language. We can go dust off the language spec if you want and point out the specific reasons that lead to that point, but it's unlikely to move you further along. – Damien_The_Unbeliever Jun 23 '16 at 10:39
  • How is the 2nd method not a logical choice? You are calling a method with 2 string parameters and the method chosen is the one with 2 string parameters. It's a perfect fit. – Dennis_E Jun 23 '16 at 10:39
  • Also, bear in mind that optional parameters were added to the language after version 1, and the mere act of going back to old code and adding defaults shouldn't have caused previously compiling code to fail to compile or pick a different method. – Damien_The_Unbeliever Jun 23 '16 at 10:41

3 Answers3

0

Yes, method resolution can be tricky, so always remember that when you write multiple overloads. They should not be ambiguous for you as they are now. The compiler just picked the shortest match, which is exactly as it should, because it is documented to do that.

There are two things you can do:

  • Rename one of the methods. This will make method resolution a piece of cake, and absolutely clear, for you and the compiler.
  • Make the last parameter required for both. This will make the method resolution very clear again: on two vs. three parameters.
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
0

It's specified (in the overload resolution, section 7.5.3 of the C# specification):

7.5.3.2 Better function member

For the purposes of determining the better function member, a stripped-down argument list A is constructed containing just the argument expressions themselves in the order they appear in the original argument list. Parameter lists for each of the candidate function members are constructed in the following way:

• The expanded form is used if the function member was applicable only in the expanded form.

Optional parameters with no corresponding arguments are removed from the parameter list

• The parameters are reordered so that they occur at the same position as the corresponding argument in the argument list.

(...)

• Otherwise if all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ then MP is better than MQ.

(etc.)

So in your case, optional parameters with an argument are taken into account on the overload resolution, so the second one (with the optional parameter), matches more specifically your call (with two arguments) than the one you expected (which has three), so it's considered "better"

Jcl
  • 27,696
  • 5
  • 61
  • 92
0

In the C# Spec (depending on version this might change) section 1.6.6.5 deals with Method Overloading. Also, this question is the same as what you are asking OVerload with optional parameters which links to the following MSDN article MSDN

Which contains the relevant section

If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

Community
  • 1
  • 1