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 回答