我有一个类型:
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;
}
}
请指导我是使用构造函数进行列表初始化的最佳实践吗? 如何使用构造函数初始化列表?
修改
请指导我是使用构造函数进行列表初始化的最佳实践吗? 如何使用构造函数将值分配给列表,因此如果没有传递值,将使用默认值?
由于
答案 0 :(得分:57)
使用集合初始值设定项
从C#3开始,您可以使用集合初始值设定项构建List并使用单个表达式填充它。以下示例构造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)
);
底线
哪种替代方案是最佳做法?或者至少是一个好的做法?你判断它! IMO,最佳做法是尽可能清楚地将程序编写给任何必须阅读它的人。在这种情况下,使用集合初始化程序对我来说是一个赢家。使用更少的代码,它可以做几乎与替代品相同的事情 - 至少,我给出的替代方案......
答案 1 :(得分:5)
你在找这个吗?
ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
new ContactNumber("555-1234"),
new ContactNumber("555-5678") };
答案 2 :(得分:3)
ContactNumbers = new List<ContactNumber>();
如果您希望传递它,请执行
public Human(List<ContactNumber> numbers)
{
ContactNumbers = numbers;
}
答案 3 :(得分:2)
您可以像任何列表一样初始化它:
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; }
答案 4 :(得分:1)
一般情况下,不要公开公开List<T>
,也不要为集合属性提供setter。此外,您可能希望复制传递列表的元素(如下所示)。否则,对原始列表的更改将影响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>();
}
另一种选择是使用带有集合的列表构造函数并删除字段初始值设定项。