如何使用构造函数初始化列表

本文关键字:列表 初始化 构造函数 何使用 | 更新日期: 2023-09-27 18:22:07

我有一个类型:

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,并使用单个表达式填充它。下面的例子构造了一个人及其联系人号码:

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
}       

然而,我甚至会更进一步,将setter设为私有,因为您通常不需要设置列表,只需要访问/修改其内容:

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>();
}

另一种选择是使用获取集合的列表构造函数并移除字段初始值设定项。