web-dev-qa-db-ja.com

いつコンストラクタを使用し、いつコレクション初期化子を使用するのですか?

以下のような10個のプロパティを持つ.Netクラスがあります:[個々のプロパティのデータ型はここでは単なるプレースホルダーであり、プリミティブ型からオブジェクト、オブジェクトのリストまで何でもかまいません]

class MyClass
{
   internal int Property1{Get;Set;}
   internal string Property2{Get;Set;}
   internal Myclass2 Property3{Get;Set;}
   internal MyAnotherClass Property4{Get;Set;}   
   internal int Property5{Get;Set;}
   internal int Property6{Get;Set;}
   internal List<string> Property7{Get;Set;}
   internal int Property8{Get;Set;}
   internal MyThirdClass Property9{Get;Set;}
   internal int Property10{Get;Set;}
}  

このクラスの目的は、データを保持することだけであり、このクラスには関数の動作がありません[POCOクラスと同様]。ここで、クラスでパラメーター化されたコンストラクターを作成してすべての値を渡してこれらのプロパティを設定するか、またはコレクション初期化子を使用してこれらのプロパティを設定する必要があるため、ここで理解しようとしています。

いずれの場合も、すべてのプロパティが設定されるため、選択的なプロパティを設定することは問題ありません。

コンストラクターを使用するアプローチを続行する場合、これらの各プロパティのプライベートメンバーを作成し、コンストラクター内でそれらを使用して、それぞれの値を割り当てます。これにより、MyClassの1つのオブジェクトを作成するためだけに10個のSetterメソッドを呼び出すことは避けられますが、10個のパラメーターを受け取るコンストラクターが作成されます。

Collection Initializerの代わりにコンストラクタを使用し、その逆を行うことをお勧めするドキュメントはありますか?個人的にはコンストラクタの作成を好みます。

5
GawdePrasad

これは内部クラスであるため、読み取り/書き込みの自動プロパティを使用してもメリットはありません。結果のILに多数のget/setメソッドを作成しています。

C#6を使用している場合、2つのオプションがあります。

1クラスを不変にします。

internal class MyClass
{
    internal MyClass(int property1, int property2, int property3, int property4, int property5, 
                     int property6, int property7, int property8, int property9, int property10)
    {
        Property1 = property1;
        Property2 = property2;
        Property3 = property3;
        Property4 = property4;
        Property5 = property5;
        Property6 = property6;
        Property7 = property7;
        Property8 = property8;
        Property9 = property9;
        Property10 = property10;
    }

    internal int Property1 { get; }
    internal int Property2 { get; }
    internal int Property3 { get; }
    internal int Property4 { get; }
    internal int Property5 { get; }
    internal int Property6 { get; }
    internal int Property7 { get; }
    internal int Property8 { get; }
    internal int Property9 { get; }
    internal int Property10 { get; }
}

このアプローチの欠点は、10個のパラメーターを持つコンストラクターが存在することです。これは、明確なコードの匂いであり、使用が面倒です。

2フィールドを使用し、オブジェクト初期化子を介してクラスを初期化します。

internal class MyClass
{
    internal int Property1;
    internal int Property2;
    internal int Property3;
    internal int Property4;
    internal int Property5;
    internal int Property6;
    internal int Property7;
    internal int Property8;
    internal int Property9;
    internal int Property10;
}

...

var x = new MyClass
{
    Property1 = 1,
    Property2 = 1,
    Property3 = 1,
    Property4 = 1,
    Property5 = 1,
    Property6 = 1,
    Property7 = 1,
    Property8 = 1,
    Property9 = 1,
    Property10 = 1,
};

このアプローチの欠点は、変更可能なデータオブジェクトが作成されることです。

これを回避する1つの方法は、クラスをいくつかの個別のクラスにリファクタリングし、それぞれが3〜4個の値を持つようにすることです。実際の値が何であるかについての情報が不足しているため、これがあなたのケースで実用的であるか望ましいかはわかりにくいです。

6
David Arno

あなたが説明したことから、10個のパラメーターを持つコンストラクターを持ち、プロパティセッターをプライベートにする方が理にかなっているように思えます。

コンストラクター内で、パラメーターからプロパティを割り当てます。

実行されて実行される議論は、プロパティを使用するのではなく、セッターで直接メンバー変数を設定するべきかどうかです。はい、パフォーマンスへの影響は最小限ですが、コンストラクタ内のプロパティストレージや他の場所のプロパティを直接参照するよりも構文的に望ましいIMHOです。

コンストラクタやプロパティをいつ使用するかは、デザインによって異なります。設定したいプロパティの既知のコレクションがある場合は、いくつかのコンストラクタを作成できます。または、空のコンストラクターを許可し、ユーザーに必要なプロパティを設定させることもできます。一部のプロパティには特定のビジネスルールがある場合があるので、コンストラクターが明らかに制御を強化します。結局のところ、これは設計上の決定です。ここで適用する実際の経験則はありません。

1
Robbie Dee