12

I accidentally overloaded a constructor in C# as follows:

public MyClass(string myString) 
{
    // Some code goes here 
}

public MyClass(string myString, bool myParameter = false) 
{
   // Some different code here
}

With this code my project compiled fine. If I call the constructor with just a string argument, how does C# decide which constructor I want to use? Why is this functionality syntactically allowed?

4
  • Is it worth inspecting the IL? This should provide some clues. Commented Jul 20, 2012 at 18:33
  • Well, the declaration compiles, but probably a call gives you a compile error saying it's ambiguous. Have you tried to make a call? Commented Jul 20, 2012 at 18:40
  • 1
    Unless you're simply asking as a point of curiosity, I'd strongly advise you change your overloads. Having overloads like this is confusing to anyone reading your code or using your code as a library. Commented Jul 20, 2012 at 18:41
  • @cytinus Its not only exist with constructors but also with overloaded methods. The same resolution applicable here as well. Commented Apr 10, 2018 at 5:46

5 Answers 5

13

From MSDN: (emphasis added)

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.

Sign up to request clarification or add additional context in comments.

Comments

11

Why is this functionality syntactically allowed?

In terms of the IL generated, the second constructor is still two arguments. The only difference is that the second argument has an attribute providing the default value.

As far as the compiler is concerned, the first is still technically a better fit when you call a constructor with a single string. When you call this with a single argument, the best match is the first constructor, and the second will not get called.

The C# specification spells this out. In 7.5, it states "... instance constructors employ overload resolution to determine which of a candidate set of function members to invoke." The specific rules are then specified in 7.5.3.2, where this specific rule applies:

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.

In this case, MP (your first constructor) has all arguments, but MQ (your second) needs "at least one optional parameter."

2 Comments

Your first paragraph is entirely correct, but the reasoning in your second paragraph is flawed. C# defines some things differently from IL. This happens to not be one of them, but the fact that the functions are different at the IL level is not a good reason for assuming that the C# compiler will pick one or the other.
@hvd True - poor choice in wording - updated to make it more clear.
2

Use of named and optional arguments affects overload resolution in the following ways:

A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.

If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. Omitted arguments for optional parameters are ignored.

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.

Quoted from MSDN.

2 Comments

First I thought that's the answer, but then realized it does not say anything about methods, just about parameters.
@achitaka-san Huh? Maybe I'm missing the obvious, but the two methods differ in their parameters, and it's that difference in parameters that matters for the question of which method to call, right?
1

Method with optional parameter will be hidden by overload.

There is even a ReSharper rule for that which warns you.

enter image description here

And here you can find useful discussion on why it's allowed. Some people even think that it's not an issue at all.

http://youtrack.jetbrains.com/issue/RSRP-287157

Comments

0

I bet it will select the first one as more appropriate.

Use of named and optional arguments affects overload resolution in the following ways:

  • A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.

  • If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are
    explicitly specified. Omitted arguments for optional parameters are
    ignored.

  • 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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.