web-dev-qa-db-ja.com

コンストラクタでリストを初期化する方法は?

私にはタイプがあります:

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

リストの初期化にコンストラクタを使用するベストプラクティスの1つであることを教えてください。コンストラクタを使用してリストを初期化する方法は?

編集:

リストの初期化にコンストラクタを使用するベストプラクティスの1つであることを教えてください。 コンストラクタを使用してリストに値を割り当てる方法、つまり、渡された値がない場合はデフォルトが使用されますか?

ありがとう

30
haansi

コレクション初期化子の使用

C#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)
);

一番下の行

どの選択肢がベストプラクティスですか?または少なくとも良い習慣ですか?あなたはそれを判断します! IMOのベストプラクティスは、プログラムを読む必要がある人にはできるだけ明確に書くことです。この場合、コレクション初期化子を使用することは私にとって勝者です。はるかに少ないコードで、代替とほぼ同じことを行うことができます-少なくとも、私が与えた代替...

57
Humberto

これを探していますか?

ContactNumbers = new List<ContactNumber>(){ new ContactNumber("555-5555"),
                                            new ContactNumber("555-1234"),
                                            new ContactNumber("555-5678") };
5
joce
ContactNumbers = new List<ContactNumber>();

渡したい場合は、

public Human(List<ContactNumber> numbers)
{
 ContactNumbers = numbers;
}
3
eouw0o83hf

リストのように初期化できます:

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; }
2
Kiril

一般に、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>();
}

別のオプションは、コレクションを取得し、フィールド初期化子を削除するリストコンストラクターを使用することです。

1
TrueWill