在构造完所有子类之后,如何在超类中执行某些代码?

时间:2010-04-30 19:41:35

标签: c# .net vb.net oop

有没有办法在C#中执行此操作?我知道子类在调用自己的构造函数之前会调用超类构造函数,但是如果我在超类上有一些代码只能在所有子类构造函数被调用之后执行呢?

5 个答案:

答案 0 :(得分:3)

实现这一目标的一种方法是选择2阶段构造并进行初始化。因此,您构造实例,然后调用initialize方法,该方法以适当的顺序调用基类Initialize

class MyBase
{
  // Only if need to do some core initialization
  public MyBase()
  {
  }

  public virtual Initialize()
  {
    // do some initialization stuff here
  }
}

class MyDerived : MyBase
{
  // Only if need to do some core initialization
  public MyDerived()
  {
  }

  public override Initialize()
  {
    // do some initialization stuff here

    // Call the base class initialization function
    base.Initialize();
  }
}

答案 1 :(得分:3)

您可以执行以下操作,但这样做有风险(请参阅下面的编辑):

public class Parent
{
    public Parent()
    {
        Initialize();
    }

    protected virtual void Initialize()
    {
        // do stuff
    }
}

public class Child : Parent
{
    protected override void Initialize()
    {
        // do child stuff
        base.Initialize();
    }
}

修改

正如Terrence在下面的评论中所建议的,这是一种冒险的方法,因为Initialize()将在Child的构造函数执行之前执行。如果在Child的构造函数中初始化了任何字段,则Initialize()使用它们时它们将不会就绪。这可能会导致令人困惑的错误。

一个简单的解决方案就是放弃父级调用Initialize(),而是让子类调用Initialize()。正如其他人所建议的那样,另一种选择是使用抽象工厂模式。

这是一个使用静态工厂方法的简单解决方案:

class Program
{
    static void Main()
    {
        Child.Create(() => new Child(5));
        Console.ReadKey();
    }
}

public abstract class Parent
{
    protected virtual void Initialize()
    {
        Console.Write(" is the number.");
    }

    public static TChild Create<TChild>(Func<TChild> childGetter)
        where TChild : Parent
    {
        var child = childGetter();
        child.Initialize();
        return child;
    }
}

public class Child : Parent
{
    private int _number;

    public Child(int number)
    {
        _number = number;
    }

    protected override void Initialize()
    {
        Console.Write(_number.ToString());
        base.Initialize();
    }
}

答案 2 :(得分:2)

C#语言中没有任何东西可以让你这样做。但是,使用创建模式可以支持它。例如,Abstract Factory模式在这里可能会有所帮助。基础工厂将确保在新创建的基类被实例化为具体子类型后调用该方法。

答案 3 :(得分:0)

class A : B
{
   public A() : base()
   {
      base.doSomething();
   }
}

class B : C
{
   public B() : base()
   {

   }

   public void doSomething() { /* ... */ }
}

class C
{
   public C() { /* ... */ }
}

执行顺序应为:

  1. Ç::构造函数()
  2. B ::构造函数()
  3. A ::构造函数()
  4. B :: doSomething的()

答案 4 :(得分:0)

我不确定你的意思 - 你不能只在最后一个子类构造函数的末尾调用超类中的代码吗?或者,您可以在实例化后直接调用它。

class Program
    {
        static void Main(string[] args)
        {
            SubSub obj = new SubSub();                
            //obj.DoStuff();
            Console.ReadLine();
        }
    }

    class Super
    {
        public Super()
        {
            Console.WriteLine("Constructing Super");
        }
        public void DoStuff()
        {
            Console.WriteLine("Doin' stuff");
        }
    }

    class Sub : Super
    {
        public Sub()
        {
            Console.WriteLine("Constructing Sub");
        }
    }

    class SubSub : Sub
    {
        public SubSub()
        {
            Console.WriteLine("Constructing SubSub");
            DoStuff();
        }
    }

这将输出:

Constructing Super 
Constructing Sub
Constructing SubSub 
Doin' stuff