我有一个类型:
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;
}
}
请指导我是使用构造函数进行列表初始化的最佳实践之一吗? 如何使用构造函数初始化列表?
编辑:
请指导我是使用构造函数进行列表初始化的最佳实践之一吗? 如何使用构造函数向列表分配值,这样如果没有传递值,将使用默认值?
谢谢
使用集合初始值设定项
从 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,最佳实践是将程序尽可能清晰地写给任何必须阅读它的人。在这种情况下,使用集合初始值设定项对我来说是一个胜利者。使用更少的代码,它可以做几乎与替代方案相同的事情——至少,我给出的替代方案......
你在找这个吗?
ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
new ContactNumber("555-1234"),
new ContactNumber("555-5678") };
ContactNumbers = new List<ContactNumber>();
如果你想传入,就拿
public Human(List<ContactNumber> numbers)
{
ContactNumbers = numbers;
}
您可以像任何列表一样初始化它:
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
}
但是,我什至会更进一步,将设置器设置为私有,因为您通常不需要设置列表,而只需访问/修改其内容:
public List<ContactNumber> ContactNumbers { get; private set; }
一般不要公开暴露
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>();
}
另一种选择是使用接受集合的列表构造函数并删除字段初始值设定项。
我需要对其进行一些细微的更改才能正常工作,也许是因为使用 dot.net core 与 dot.net
var human = new Human(1, "Address", "Name", DayOfTheWeek.Tuesday )
{
ContactNumbers = new List<ContactNumber>()
{new ContactNumber(122,555), new ContactNumber(332,332) }
};
}
public class Human
{
public int Id { get; set; }
public string Address { get; set; }
public string Name { get; set; }
public DayOfTheWeek DayOfTheWeek { get; set; }
public List<ContactNumber> ContactNumbers { get; set; }
public Human(int id, string address, string name, DayOfTheWeek dayOfWeek )
{
Id = id;
Address = address;
Name = name;
DayOfTheWeek = dayOfWeek;
}
}
public class ContactNumber
{
public int HomeNumber { get; set; }
public int WorkHumber { get; set; }
public ContactNumber(int homeNumber, int workNumber)
{
homeNumber = HomeNumber;
workNumber = WorkHumber;
}
}
public enum DayOfTheWeek
{
Monday,
Tuesday,
Wednesday
}
}