I have a type:
public class Human
{
public int Id { get; set; }
public string Address { get; set; }
public string Name { get; set; }
public List
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; }
ContactNumbers = new List<ContactNumber>();
If you want it to be passed in, just take
public Human(List<ContactNumber> numbers)
{
ContactNumbers = numbers;
}
Are you looking for this?
ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
new ContactNumber("555-1234"),
new ContactNumber("555-5678") };
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.
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...