web-dev-qa-db-ja.com

C#独自のコンストラクタの後に基本クラスのコンストラクタを呼び出しますか?

どうすれば基本クラスのコンストラクタを呼び出すことができますafter自分のコンストラクタを呼び出しましたか?

問題は、基本クラスのコンストラクターが(サブクラスでオーバーライドされた)抽象メソッドを呼び出し、サブクラスのコンストラクターで初期化された変数xにアクセスする必要があるかどうかです。

短いコード例:

_abstract class BaseClass
{
    protected string my_string;

    protected abstract void DoStuff();

    public BaseClass()
    {
        this.DoStuff();
    }
}

class SubClass : BaseClass
{
    private TextBox tb;

    public SubClass()
        : base()
    {
        this.my_string = "Short sentence.";
    }

    protected override void DoStuff()
    {
        // This gets called from base class' constructor
        // before sub class' constructor inits my_string
        tb.Text = this.my_string;
    }
}
_

編集:回答に基づいて、明らかに不可能です。作成されたSubClassのすべてのオブジェクトでthis.DoStuff();を呼び出す自動化された方法はありますか?もちろん、サブクラスのコンストラクターの他のすべての行の後にthis.DoStuff();を追加することもできますが、これらのクラスが約100あるため、ばかげた感じがします。他の解決策、または手動の解決策を使用する必要がありますか?

19
user1632861

できません。

また、通常、コンストラクターでvirtualメソッドを呼び出さないでください。これを見てください answer


あなたが書いた単純な例ではなく、実際のコードに応じて、ベースコンストラクタとDoStuffメソッドのパラメータとして値を渡すことができます。例えば:

_abstract class BaseClass
{
    private string my_string;

    protected abstract void DoStuff(string myString);

    public BaseClass(string myString)
    {
        this.my_string = myString;
        this.DoStuff(this.my_string);
    }
}

class SubClass : BaseClass
{
    private TextBox tb;

    public SubClass()
        : base("Short sentence.")
    {
    }

    protected override void DoStuff(string myString)
    {
        tb.Text = myString;
    }
}
_

実際のコードでそれが不可能な場合は、複数のDoStuff()を作成するとうまくいきます。また、SubClassクラスをシールして、DoStuffメソッドをもう一度変更して他の誰もバグを導入できないようにすることも忘れないでください。

25
ken2k

メソッドを呼び出すインスタンスのコンストラクターが実行されていない可能性があるため、コンストラクターで抽象メソッドを呼び出さない

仮想メソッドが呼び出されると、メソッドを実行する実際のタイプは実行時まで選択されません。コンストラクターが仮想メソッドを呼び出すときに、メソッドを呼び出すインスタンスのコンストラクターが実行されていない可能性があります。このルールの違反を修正するには、型のコンストラクター内から型の仮想メソッドを呼び出さないでください。

http://msdn.Microsoft.com/en-us/library/ms182331%28v=vs.80%29.aspx

4

コンストラクタが実際に実行される前にクラスを構築できない理由はありますか?派生クラスの作成方法にはより高いレベルの責任が必要であり、おそらくベストプラクティスではありませんが、機能するようです。

abstract class BaseClass {
    protected string my_string;

    protected abstract void DoStuff();

    public BaseClass() {
        this.DoStuff();
    }
}

class SubClass: BaseClass {
    TextBox tb;

    bool Constructed = false;
    void Constructor() {
        if (!Constructed) {
            Constructed = true;
            this.my_string = "Short sentence.";
        }
    }
    public SubClass()
        : base() {
        Constructor();
    }

    protected override void DoStuff() {
        Constructor();
        // This gets called from base class' constructor
        // before sub class' constructor inits my_string
        tb.Text = this.my_string;
    }
}
0
Darin