7

So I need to understand which way is the correct/best one?

First way:

class Customer
{
    string firstName;
    string lastName;

    public Customer(string firstName="non", string lastName="applicable")
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Second way:

class Customer
{
    string firstName;
    string lastName;

    public Customer()
    : this("non","applicable")
    { }

    public Customer(string firstName, string lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

If I'm creating a method printFullName(), it works in both cases. So which one to chose? The first one seems easier to me.

catalin
  • 946
  • 6
  • 14
  • 31
  • There are [many](https://stackoverflow.com/q/6132010/1997232) "overload vs optional parameters" questions, but parameterless constructor might be a bit more special you think? – Sinatr Jan 11 '18 at 11:18
  • 1
    I don't think there's any big difference, so choose the one that is clearer for you. This question seems to fall into "primarily opinion based" category. – Pikoh Jan 11 '18 at 11:21
  • Taking serialization into account, I think you [may want](https://stackoverflow.com/a/12561384/1997232) to have parameterless constructor. – Sinatr Jan 11 '18 at 11:25
  • 1
    @Pikoh There is a difference - what would happen if you called both with `new Customer("Jim", null)` ? – ZippyZippedUp Jan 11 '18 at 11:25
  • @ZippyZippedUp yep, you're right. I realized that would be a problem after Scott Hannen answer. – Pikoh Jan 11 '18 at 11:27
  • If `Customer` objects will be created based on user input, you should also consider what you want to do in the case of null strings, empty strings and whitespace being passed to the constructor. Are you happy in your examples that a customer could be named [whitespace] [empty string]? – ZippyZippedUp Jan 11 '18 at 11:37
  • That's a good case for creating a `Name` class. Whatever the rules are for creating a name (no nulls, empty strings allowed or not, length, trimming) are encapsulated in one place, as opposed to having first and last name properties in various places and hoping the rules get applied. Wherever you have an instance of `Name` you know it follows the rules because the constructor enforces them. – Scott Hannen Jan 11 '18 at 12:01
  • You should accept an answer – Kellen Stuart Nov 14 '18 at 20:05

2 Answers2

7

The second way is better, because it looks like it's your intent to use "non" and "applicable" as the first and last name if they supply no inputs.

If you have just one constructor with optional arguments, someone could supply a first name and have the last name be "applicable," like "Bob applicable."

It's a minor difference because a) it works either way, and b) a consumer can tell what the default parameters are. But the second option seems more in line with your apparent intent.

To be really particular I'd reconsider those defaults. Should someone be able to create a customer without a name? If so then perhaps the name should be null. Perhaps CustomerName should be a separate class, and Customer has a Name property of of type CustomerName. The reason I'm splitting hairs over that is because you want to know if you have a name or not. Once you supply a fake name that's harder to determine. You could send out hundreds of letters to customers named "non applicable."

Scott Hannen
  • 27,588
  • 3
  • 45
  • 62
7

In terms of semantics, both ways are correct. Some of the differences between the two are

First way: Invoke the constructor as:

  1. new Customer(firstName="first");
  2. new Customer(lastName="last");
  3. new Customer("first", "last");
  4. new Customer();

Second way: Invoke the constructor as:

  1. new Customer("first", "last");
  2. new Customer();

So the first way will give you more flexibility in how you can invoke the constructor.

h-rai
  • 3,636
  • 6
  • 52
  • 76