4

I have a simple question about constructors in C#. Will these two code snippets behave the same way?

Code snippet #1:

public class foo
{
    public foo(string a = null, string b = null)
    {
      // do testing on parameters
    }
}

Code snippet #2:

public class foo
{
    public foo()
    {
    }

    public foo(string a)
    {
    }

    public foo(string a, string b)
    {
    }
}

EDIT: And if I add this to the code snippet #1? It may look a really bad idea, but I'm working on refactoring a legacy code, so I'm afraid if I do sth that will cause damage to other piece of that uses that class.

public class foo
{
    public foo(string a = null, string b = null)
    {
       if (a == null && b == null)
            {
                // do sth
            }else if (a != null && b == null)
            {
                // do sth
            }
            if (a != null && b != null)
            {
                // do sth
            }
            else
            {

            }
    }
}
7
  • 6
    try it yourself and see?? Commented Apr 18, 2018 at 16:41
  • 2
    One thing that you may want to ask yourself as well, what happens if you only want to pass in the value for b in your constructor? Commented Apr 18, 2018 at 16:42
  • 5
    If you have multiple constructors, you should make it a habit to use Construcor Chaining (stackoverflow.com/questions/1814953/…). Right now you would have to write the same code over and over again. However with chaining you chain from the Consturctor with the least parametrs to the one with the most, having the real code only in the final one. Commented Apr 18, 2018 at 16:45
  • 2
    Yes neither one compiles. Commented Apr 18, 2018 at 16:46
  • 1
    Class is not a keyword =) Commented Apr 18, 2018 at 16:54

3 Answers 3

9

The answer is no, the two are not going to behave the same.

The first snippet does not let your constructor decide if it has been called with a default parameter for a and/or b, or the caller has intentionally passed null. In other words, passing nulls intentionally becomes allowed, because you cannot implement a meaningful null check.

Another aspect in which these two code snippets would definitely differ - using constructors through a reflection:

  • The first snippet would provide one constructor. Reflection callers would need to deal with passing two parameters to it, or allowing optional parameters with binding flags (look at the demo provided by Jcl).
  • The second snippet would provide three separate constructors. Reflection callers would need to pick the one they wish to use.
Sign up to request clarification or add additional context in comments.

6 Comments

Having a parameterless constructor may also be precondition to being usable - f.e. when dealing with wpf/xaml.
While the answer is correct, you can use reflection with optional parameters (with the correct binding flags). I've made a simple example: dotnetfiddle.net/sdKtSd
@RufusL I mean checking for null becomes useless, because you don't know if a caller passed you a null (which is an error) or the caller didn't include the argument and you've got the default (which is not an error).
@Jcl Thank you very much for the comment. I edited to make this a separate point, and referenced your demo in the answer.
@AymenBenTanfous As long as your “do something“ doesn’t include throwing an exception, you should be fine. Also make sure that the class that you are modifying is not instantiated through reflection.
|
2

No. Try using named arguments. The overload version will not compile. Because a hasn't been given a value in the latter case.

var test = new foo1(b: "nope");
var test2 = new foo2(b: "nope");//CS7036 : There is no argument given that corresponds to the required formal parameter of

Comments

2

if your are looking for a way to create an object with optional parameters just create inside your class a static factory method with optional or named parameter:

public class Foo
{
    public Foo(string a, string b, string c) { }

    public static Foo createInstance(string a = null, string b = null, string c = null) => new Foo(a, b, c);
}

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.