1

以下のコードは、抽象コンストラクターが子コンストラクターの前に呼び出されるため、例外をスローします。

プログラムの別の部分からいくつかのロジックをカプセル化する抽象クラスを提供する必要があります。ただし、子クラスがこれに影響を与えることなく、作成後に抽象メンバーが正しく初期化されているかどうかも確認する必要があります。

以下のコンパイル例は私の質問を説明するはずです。

using System;

namespace Stackoverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = new Thing(5);
            var y = new Child(x);
        }
    }

    class Child : AbstractParent
    {
        Thing childthing;

        public Child(Thing provided) : base(){
            childthing = provided;
        }

        public override void Initialise(){
            //Exception is thrown here - childthing is still null
            parentthing = childthing.Add(1);
        }
    }

    abstract class AbstractParent
    {
        protected Thing parentthing;

        public AbstractParent(){
            Initialise();
            AssertThingyNotNull();
        }

        private void AssertThingyNotNull(){
            if (parentthing == null) throw new Exception("Waaa");
        }

        public abstract void Initialise();

    }

    class Thing
    {
        private int i;

        public Thing(int i){
            this.i = i;
        }

        public Thing Add(int b){
            i += b;
            return new Thing(i);
        }
    }
}

編集#1:

発信者に反映することでこれを行う方法はありますか (子の権利の作成者である必要がありますか?)、その呼び出しの最後に反応しますか?

編集 #2: 子を作成する .ctor を取得するのは簡単です。メソッドを操作することは、不可能と悪い考えの間のように思えます。

        foreach (StackFrame frame in new StackTrace().GetFrames())
        {
            Console.WriteLine(frame.GetMethod().Name);
        }
4

3 に答える 3

5

基本的に、できません。これが、コンストラクターから仮想 (または抽象) メンバーをできるだけ呼び出さないようにする必要がある理由です。不完全なコンテキストで実行されるコードになる可能性があります。基本クラスのコンストラクターが呼び出される前に変数初期化子が実行されますが、コンストラクター本体内のコードは実行されません。

初期化を実行する必要があり、派生クラス コンストラクターの実行中にのみ実行したい場合は、派生クラス コンストラクターInitialiseから呼び出すだけで開始できます。

于 2012-07-16T16:19:31.477 に答える
2

マイクロソフトが行ったことと同様のことができますInitializeComponent()

それから、できる限り子供たちにそれを呼び出させます。

于 2012-07-16T16:21:40.710 に答える
1

これを試して。

編集済み = よりクリーンなバージョン。

using System;

namespace ConsoleApplication3
{
class Program
{
    static void Main(string[] args)
    {
        var x = new Thing(5);
        var y = new Child(x);
    }
}

class Child : AbstractParent
{
    public Child(Thing provided)
        : base()
    {
        parentthing = provided;
        base.Initialise();
    }
}

abstract class AbstractParent
{
    protected Thing parentthing;

    public AbstractParent()
    {

    }

    private void AssertThingyNotNull()
    {
        if (parentthing == null) throw new Exception("Waaa");
    }

    public void Initialise()
    {
        AssertThingyNotNull();
    }

}

class Thing
{
    private int i;

    public Thing(int i)
    {
        this.i = i;
    }

    public Thing Add(int b)
    {
        i += b;
        return new Thing(i);
    }
}

}

于 2012-07-16T16:36:42.577 に答える