trsing’s diary

勉強、読んだ本、仕事で調べたこととかのメモ。

EFFECTIVE C# 6.0/7.0 読書メモ 項目12、13

項目12 メンバには割り当て演算子よりもオブジェクト初期化子を使用すること

オブジェクト初期化子を使用するメリット
  • コンストラクタに関わらずメンバ変数を確実に初期化することができる
  • 将来新しいコンストラクタを追加した場合でも、メンバ変数の初期化忘れを防ぐことができる

通常、複数のコンストラクタが用意される。コンストラクタでメンバ変数を初期化する場合、初期化し忘れ、整合性が取れなくなる、手間がかかるといったデメリットが生じる。

オブジェクト初期化子を使うべきでないケース
  • オブジェクトを0またはnullに初期化するケース

システム規定の初期化処理では、コードを実行する前にすべての値が0に初期化される(メモリブロック全体が0に設定される)。独自のコードを追加すると0を再設定することになり無駄。

  • 同一のオブジェクトに対して複数回の初期化を行うケース

オブジェクト初期化子を使用し、コンストラクタでも初期化すると、オブジェクト初期化子で作成したオブジェクトは即座にガベージになる。対策方法は項目14を参照。

  • 初期化時における例外処理に対応させるケース

初期化コードはtryブロックで囲うことができない。例外が生じるとオブジェクトの外側へ伝搬される。初期化コードをコンストラクタ内に移動させて、例外を適切に処理するような復旧用コードを作成すること。

オブジェクト初期化子が実行されるタイミング

すべてのコンストラクタ(親クラスのコンストラクタ含む)よりも先に実行される。初期化子が記述された順序で実行される。
※詳細は項目14参照

13 staticメンバを適切に初期化すること

  • staticメンバ変数は、型のインスタンスが作成されるよりも前に初期化される(staticメンバ初期化子、staticコンストラクタ)
  • staticコンストラクタは1つのみ定義可能。引数を取ることはできない。
  • staic変数初期化子、staticコンストラクタ以外の方法でstaticメンバ変数を初期化すべきではない。
  • 例外が出る可能性がある場合はstaticコンストラクタを使用するべき。
例外について

staticコンストラクタはCLRから呼び出される。staticコンストラクタ内で発生した例外が処理されない場合、CLRは例外をスローしてプログラムを停止させる。この例外を呼び出し元が処理できたとしても、staticコンストラクタによる初期化がされていない状態になる。

static変数初期化子だと、発生した例外をクラス自身で処理することはできない。staticコンストラクタの場合にはクラス内での例外処理が可能。