4

I'm currently studying C# and I'm learning about constructors and the chain calling of constructors so as not to have to paste the same code (the same value for variables) in each constructor.

I have three constructors, one with no parameters, one with three parameters and one with four parameters. What I'm looking to do is, use the default constructor to call the constructor with three parameters, passing default values for the parameters (variables) and the constructor that has three parameters, I'm looking for that to call the constructor with four parameters. I seem to have the first one sorted listing the default values but I'm struggling how to write the constructor with three parameters and then get this to call the constructor with four parameters if required.

The default constructor should assign all instance variables of the type string to string.Empty.

public Address()
{
   m_street = string.Empty;
   m_city = string.Empty;
   m_zipCode = string.Empty;
   m_strErrMessage = string.Empty;
   m_country = Countries;
}


public Address(string street, string city, string zip)
{
}

public Address(string street, string city, string zip, Countries country)
{
}

I was looking to do the following but it doesn't work:-

public Address(string street, string city, string zip)
     : this street, string.Empty, city, string.Empty, zip, string.Empty
{
}
1
  • Looks like you forgot some brackets there. And several keywords... Commented Aug 4, 2011 at 16:08

6 Answers 6

11

You should generally chain the constructor with the least information onto the one with the most information, not the other way round. That way each field can be assigned in precisely one place: the constructor with the most information. You've actually described that behaviour in your post - but then your code does something entirely different.

You also need to use the right syntax for constructor chaining, which is:

: this(arguments)

For example:

public class Address
{
    private string m_street;
    private string m_city;
    private string m_zipCode;
    private string m_country;

    public Address() : this("", "", "")
    {
    }


    public Address(string street, string city, string zip)
        : this(street, city, zip, "")
    {
    }

    public Address(string street, string city, string zip, string country)
    {
        m_street = street;
        m_city = city;
        m_zip = zip;
        m_country = country;
    }
}

For more information on constructor chaining, see this article I wrote a while ago.

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

Comments

3

The idea would be to leave the logic of the instantiation to the constructor that takes in the most parameters and use the others as methods that only pass values to that constructor, that way you only write the code once.

Try this:

public Address() 
  : this(String.Empty, String.Empty, String.Empty)
{
}


public Address(string street, string city, string zip) 
  : this(street, city, zip, null)
{
}

public Address(string street, string city, string zip, Countries country) 
{
    m_street = street;
    m_city = city;
    m_zipCode = zip;
    m_country = Countries;
    m_strErrMessage = string.Empty;
}

3 Comments

With your suggestion for the constructor with there parameters, it doesn't seem to work:- public Address(string street, string city, string zip) : this(street, city, zip, Nothing) { } The keyword 'Nothing' is not accepted and brings up an exception. I tried replacing it with String.Empty but that doesn't work either. As the forth parameter (country) extracts a string value from an Enum, not sure if this is the problem.
Sorry, I actually code in Visual Basic and so I wrote Nothing by mistake, just replace Nothing with null. I fixed the answer already.
But to clarify I doubt that works if Countries is an enum, what's Countries type?
3

You need ():

public Address(string street, string city, string zip)
      : this(street, string.Empty, city, string.Empty, zip, string.Empty)
{
}

This will call the Address constuctor with 3 of 6 args specified (if there is one), is that what you are trying to do?

1 Comment

You also need a constructor that looks like public Address(string street, string unknown1, string city, string unknown2, string zip, string unknown3).
1

Your syntax is close. Try this

public Address(string street, string city, string zip)
      : this( street, string.Empty, city, string.Empty, zip, string.Empty )
{
}

In your example you should also remove the default constructor and put the initialization of the variables into the constructor that is at the end of the chain. That one being the one that takes a country in your example.

Hope this helps.

Comments

1

You can use this to call other constructors on the same object. The general idea is to do the actual initialisation of properties/fields in the most complex constructor and chain progressively simpler ones together giving default values.

Assuming Countries is an Enum, such as:

public enum Countries
{
   NotSet = 0,
   UK,
   US
}

You can do this(Note that your enum doesnt have to have a Default state such as NotSet, but if it doesnt, you just need to decide what the default is if the value is not specified):

public Address()
  :this(String.Empty,String.Empty,String.Empty)
{        
}

public Address(string street, string city, string zip)
  :this(street,city,zip,Countries.NotSet)
{
}

public Address(string street, string city, string zip, Countries country) 
{ 
    m_street = street;
    m_city = city
    m_zipCode = zip;
    m_country = country;
}

2 Comments

With your suggestion for the constructor with there parameters, it doesn't seem to work:- public Address(string street, string city, string zip) : this(street, city, zip, String.Empty) { } I tried replacing 'String.Empty' with 'Nothing' as another user suggested but that doesn't work either. As the forth parameter (country) extracts a string value from an Enum, not sure if this is the problem but as said, the second constructor containing three parameters does not accept 'String.Empty' as a stand-in placeholder for parameter 4.
@Enverlap - If Countries is an Enum, then you just need to either define a default value in your enum and pass that, or perhaps choose a default from your current enum. See updated answer.
0

You need parenthesis for the constructor chaining, like so:

public Address(string street, string city, string zip)
          : this (street, string.Empty, city, string.Empty, zip, string.Empty)
    {
    }

Also, you are calling a constructor with 6 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.