同僚からこの質問がありましたが、クラスには常にデフォルトのコンストラクターを含める必要がありますか?もしそうなら、なぜですか?いいえの場合、なぜですか?
例
public class Foo {
Foo() { }
Foo(int x, int y) {
...
}
}
また、専門家からこれについていくつかの光を得ることに興味があります。
同僚からこの質問がありましたが、クラスには常にデフォルトのコンストラクターを含める必要がありますか?もしそうなら、なぜですか?いいえの場合、なぜですか?
例
public class Foo {
Foo() { }
Foo(int x, int y) {
...
}
}
また、専門家からこれについていくつかの光を得ることに興味があります。
オーバーロードされたコンストラクターを提供しない場合、コンパイラーがデフォルトのコンストラクターを生成することに注意する必要があります。つまり、
public class Foo
{
}
コンパイラはこれを次のように生成します。
public class Foo
{
public Foo() { }
}
ただし、他のコンストラクターを追加するとすぐに
public class Foo
{
public Foo(int x, int y)
{
// ...
}
}
コンパイラーは、デフォルトのコンストラクターを自動的に生成しなくなります。デフォルトのコンストラクターの存在に依存する他のコードでクラスがすでに使用されていた場合Foo f = new Foo();
、そのコードは壊れます。
誰かがデータを提供せずにクラスを初期化できるようにしたくない場合は、デフォルトのコンストラクターを作成する必要があります。これはprivate
、入力データなしでインスタンスが構築されるのを防いでいるという事実を明示するものです。
ただし、デフォルトのコンストラクター(パブリックまたはプライベート)を提供する必要がある場合があります。前述のように、一部のタイプのシリアル化にはデフォルトのコンストラクターが必要です。クラスに複数のパラメーター化されたコンストラクターがあるが、「低レベル」の初期化が必要な場合もあります。その場合、パラメーター化されたコンストラクターからチェーンされたプライベートのデフォルトコンストラクターを使用できます。
public class Foo
{
private Foo()
{
// do some low level initialization here
}
public Foo(int x, int y)
: this()
{
// ...
}
public Foo(int x, int y, int z)
: this()
{
// ...
}
}
いくつかのもの(シリアル化など)には、デフォルトのコンストラクターが必要です。ただし、それ以外では、デフォルトのコンストラクターは、意味がある場合にのみ追加する必要があります。
たとえば、Foo.X
andFoo.Y
プロパティが構築後に不変である場合、デフォルトのコンストラクタは実際には意味がありません。それが「空の」Fooに使用されたとしても、静的Empty
アクセサーはより発見可能です。
私はノーと言うでしょう、間違いなく常にではありません。いくつかの値に初期化する必要のある読み取り専用フィールドを持つクラスがあり、妥当なデフォルトがない(または存在したくない)と仮定しますか?このシナリオでは、パラメーターなしのコンストラクターは意味がないと思います。
デフォルトのコンストラクターを持つことは、そのようなオブジェクトを持つことが理にかなっている場合にのみ良い考えです。
そのようなコンストラクターから有効な状態にないオブジェクトを生成する場合、それが実行できる唯一のことはバグを導入することです。
補足として、クラスの代わりにstructを使用する場合、デフォルトのコンストラクターを除外する方法はなく、自分で定義することもできないことに注意してください。したがって、定義するコンストラクターに関係なく、デフォルトの状態が構造体(すべての変数がデフォルトの状態(通常は値型の場合は0、参照型の場合はnull)に設定されている場合)は、構造体の実装を中断しません。
はい混乱を避けるために、デフォルトのコンストラクターを用意することをお勧めします。私は人々がデフォルトコンストラクター内で何もしないのを見てきましたが(Microsoft自身のクラスでも)、オブジェクトは自動的にdefault(type)を取得するのでそれを維持したいと思っています。デフォルトのコンストラクターを指定しないクラス、.NETは自動的にそれらを追加します。
汎用シリアライザーにとって意味があるため、既存のシリアライザーを使用する場合、シリアル化にはデフォルトコンストラクターが必要です。それ以外の場合は、独自の実装を作成する必要があります。
ほとんどの場合、デフォルトのコンストラクターが適切です。しかし、「常に」という言葉を使用しているので、必要なのは1つの反例だけです。フレームワークを見ると、たくさん見つかります。たとえば、System.Web.HttpContextです。
ジェネリック型は、デフォルトのコンストラクターがある場合にのみ、C#手段(リフレクションなし)でインスタンス化できます。また、new()
ジェネリック型の制約を指定する必要があります。
void Construct<T>()
where T : new()
{
var t = new T();
...
}
デフォルトのコンストラクターを持たないジェネリック型引数として型を使用してこのメソッドを呼び出すと、コンパイラーエラーが発生します。