Как инициализировать список с помощью конструктора?
У меня есть тип:
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;
}
}
Прошу вас посоветовать в числе лучших практик использования конструктора для инициализации списка?
Как инициализировать список с помощью конструктора?
Edit:
Прошу вас посоветовать в числе лучших практик использования конструктора для инициализации списка?
Как назначить значения для списка с помощью конструктора, поэтому, если значение, принятое по умолчанию, будет использоваться?
Спасибо
Ответы
Ответ 1
Использование инициализатора коллекции
Из С# 3 вы можете использовать инициализаторы коллекции для создания списка и заполнения его одним выражением. В следующем примере строятся объекты Human и ContactNumbers:
var human = new Human(1, "Address", "Name") {
ContactNumbers = new List<ContactNumber>() {
new ContactNumber(1),
new ContactNumber(2),
new ContactNumber(3)
}
}
Специализация конструктора Human
Вы можете изменить конструктор класса Human
, чтобы обеспечить способ заполнения свойства ContactNumbers
:
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)
);
Нижняя строка
Какая альтернатива - лучшая практика? Или, по крайней мере, хорошая практика? Вы это судите! ИМО, лучшая практика заключается в том, чтобы написать программу как можно яснее всем, кто должен ее прочитать. Использование инициализатора коллекции является для меня победителем, в данном случае. С гораздо меньшим количеством кода он может делать почти то же самое, что и альтернативы - по крайней мере, альтернативы, которые я дал...
Ответ 2
Вы ищете это?
ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
new ContactNumber("555-1234"),
new ContactNumber("555-5678") };
Ответ 3
ContactNumbers = new List<ContactNumber>();
Если вы хотите, чтобы он был передан, просто возьмите
public Human(List<ContactNumber> numbers)
{
ContactNumbers = numbers;
}
Ответ 4
Вы можете инициализировать его точно так же, как и любой список:
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
}
Однако я бы даже сделал еще один шаг и сделал setter частным, так как вам часто не нужно устанавливать список, а просто получать доступ/изменять его содержимое:
public List<ContactNumber> ContactNumbers { get; private set; }
Ответ 5
В общем случае не публиковать List<T>
публично и не предоставлять сеттеры для свойств коллекции. Кроме того, вы можете скопировать элементы переданного списка (как показано ниже). В противном случае изменения в исходном списке будут влиять на экземпляр Human.
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>();
}
Другой вариант - использовать конструктор списка, который принимает коллекцию и удаляет инициализатор поля.