How to initialize a list with constructor?

131,728

Solution 1

Using a collection initializer

From C# 3, you can use collection initializers to construct a List and populate it using a single expression. The following example constructs a Human and its ContactNumbers:

var human = new Human(1, "Address", "Name") {
    ContactNumbers = new List<ContactNumber>() {
        new ContactNumber(1),
        new ContactNumber(2),
        new ContactNumber(3)
    }
}

Specializing the Human constructor

You can change the constructor of the Human class to provide a way to populate the ContactNumbers property:

public class Human
{
    public Human(int id, string address, string name, IEnumerable<ContactNumber> contactNumbers) : this(id, address, name)
    {
        ContactNumbers = new List<ContactNumber>(contactNumbers);
    }

    public Human(int id, string address, string name, params ContactNumber[] contactNumbers) : this(id, address, name)
    {
        ContactNumbers = new List<ContactNumber>(contactNumbers);
    }
}

// Using the first constructor:
List<ContactNumber> numbers = List<ContactNumber>() {
    new ContactNumber(1),
    new ContactNumber(2),
    new ContactNumber(3)
};

var human = new Human(1, "Address", "Name", numbers);

// Using the second constructor:
var human = new Human(1, "Address", "Name",
    new ContactNumber(1),
    new ContactNumber(2),
    new ContactNumber(3)
);

Bottom line

Which alternative is a best practice? Or at least a good practice? You judge it! IMO, the best practice is to write the program as clearly as possible to anyone who has to read it. Using the collection initializer is a winner for me, in this case. With much less code, it can do almost the same things as the alternatives -- at least, the alternatives I gave...

Solution 2

Are you looking for this?

ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
                                            new ContactNumber("555-1234"),
                                            new ContactNumber("555-5678") };

Solution 3

You can initialize it just like any list:

public List<ContactNumber> ContactNumbers { get; set; }

public Human(int id)
{
    Id = id;
    ContactNumbers = new List<ContactNumber>();
}

public Human(int id, string address, string name) :this(id)
{
    Address = address;
    Name = name;
    // no need to initialize the list here since you're
    // already calling the single parameter constructor
}       

However, I would even go a step further and make the setter private since you often don't need to set the list, but just access/modify its contents:

public List<ContactNumber> ContactNumbers { get; private set; }

Solution 4

ContactNumbers = new List<ContactNumber>();

If you want it to be passed in, just take

public Human(List<ContactNumber> numbers)
{
 ContactNumbers = numbers;
}

Solution 5

In general don't expose List<T> publicly, and don't provide setters for collection properties. Also, you may want to copy the elements of the passed list (as shown below). Otherwise changes to the original list will affect the Human instance.

public class Human
{
    public Human()
    {
    }

    public Human(IEnumerable<ContactNumber> contactNumbers)
    {
        if (contactNumbers == null)
        {
            throw new ArgumentNullException("contactNumbers");
        }

        _contactNumbers.AddRange(contactNumbers);
    }

    public IEnumerable<ContactNumber> ContactNumbers
    {
        get { return _contactNumbers; }
    }

    private readonly List<ContactNumber> _contactNumbers = new List<ContactNumber>();
}

Another option is to use the list constructor that takes a collection and remove the field initializer.

Share:
131,728
haansi
Author by

haansi

Updated on February 02, 2020

Comments

  • haansi
    haansi over 4 years

    I have a type:

    public  class Human
    {
        public int Id { get; set; }
        public string Address { get; set; }
        public string Name { get; set; }
        public List<ContactNumber> ContactNumbers { get; set; }
    
        public Human(int id)
        {
            Id = id;
        }
    
        public Human(int id, string address, string name,
                     List<ContactNumber> contactNumbers) :
            this(id)
        {
            Address = address;
            Name = name;
            ContactNumbers = contactNumbers;
        }        
    }
    

    Please guide me is among best practices to use constructor with for list initialization? How to initialize a list using constructor?

    Edit:

    Please guide me is among best practices to use constructor with for list initialization? How to assign values to list using a constructor, so if no value passed a default will be used?

    Thanks

  • haansi
    haansi over 12 years
    Thanks @eouw0o83hf, I am sorry for my not enough explaination. I want to pass numbers for list<ContactNubmer> using constructor. Kindly also tell is it a good way to pass values to list just like we pass other values ?
  • haansi
    haansi over 12 years
    Thanks @Lirik, Kindly guide how to pass values to list from constrcot ? also guide is it standard way to use constroctor to pass values to a property which is a list basically ?
  • haansi
    haansi over 12 years
    Thanks @TrueWill, can we not fill a list and pass it to constructor just as we pass other values through constructor and if there is no values then assign a default ? how it will be done ? Is it a good way to do so ?
  • TrueWill
    TrueWill over 12 years
    It depends. You're passing a reference. Do you want the Human's contacts to change when the original contact list is changed? If you want a default list I'd normally add a default constructor to Human that would create an empty list. Avoid null references whenever possible. Also avoid special-casing empty lists.
  • TrueWill
    TrueWill over 12 years
    Are you looking for the params keyword?
  • haansi
    haansi over 12 years
    No TrueWill, I want to assign values to list<contactnumber> using constructor. Please also guide how to handle if no values is assign (what would be default) ? Is it a standard way ?
  • TrueWill
    TrueWill over 12 years
    You might want to post your desired calling code. What code do you want to write to create a Human?
  • haansi
    haansi over 12 years
    TrueWill please see my 2nd constructor. Is it a good way ? or how it should be improved ?
  • eouw0o83hf
    eouw0o83hf over 12 years
    The second constructor is good. It will appropriately set the property