Effective C# 3rd 読書メモ 16 コンストラクタ内で仮想関数を呼び出してはいけない

仮想関数は、コンストラクタの中で(C++プログラマーにとっては)奇妙な振る舞いをする。
たとえば、以下のコードを実行すると、出力されるのは「Set by initializer」である。

class Program
{
    public static void Main(string[] args)
    {
        new Derived("Constructed in main");
    }
}

class B
{
    protected B()
    {
        // 1. ベースクラスのコンストラクタが呼び出される
        VFunc(); // 2. VFunc() は派生クラスのものが呼び出される
    }

    protected virtual void VFunc()
    {
        WriteLine("VFunc in B");
    }
}

class Derived : B
{
    private readonly string _msg = "Set by initializer";

    public Derived(string msg)
    {
        _msg = msg;
    }

    protected override void VFunc()
    {
        // 3. ベースクラスのコンストラクタによって呼び出される
        // このとき、派生クラスのコンストラクタはまだ呼ばれてないので、
        // _msgは初期化子で設定された値になっている
        WriteLine(_msg);
    }
}

一般に、コンストラクタで仮想関数を実行すると、コードがひどく壊れやすくなる。
派生クラスが何をするか完全にコントロールすることはできないからだ。
コンストラクタ内での仮想関数の実行は禁止すべき(Never call)である。

コメントをどうぞ

コメントを残す