简体   繁体   中英

How do I execute some code in a superclass after all the subclasses have been constructed?

Is there a way to do this in C#? I know that the subclass will call the superclass constructor before calling its own constructor, but what If I have some code on the superclass that should only be executed after all the subclasses constructors have been called?

One way to achieve this would be to go for a 2 phase construct and initialize. So you construct the instances and then call an initialize method which invoked the base class Initialize in the appropriate order

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();
  }
}

You could do the following, but it is risky (see my Edit below):

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();
    }
}

Edit

As suggested in Terrence's comment below, this is a risky approach because Initialize() will be executed before Child 's constructor is executed. If there are any fields initialized in Child 's constructor, they won't be ready if they are used by Initialize() . This could cause confusing bugs.

A simple solution would be to give up on the Parent calling Initialize() and instead have the child classes call Initialize() . As others have suggested, another option would be to use the abstract factory pattern.

Here is a simple solution that uses a static factory method:

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();
    }
}

There is nothing built into the C# language that lets you do this. However, using a creation pattern could support it. For example, the Abstract Factory pattern might be helpful here. The base factory would ensure that a method is called on the newly created base class once it has been instantiated as the concrete child type.

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

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

   }

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

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

Execution Order should be:

  1. C::ctor()
  2. B::ctor()
  3. A::ctor()
  4. B::doSomething()

I'm not sure what you mean - can't you just call the code in the super class at the end of our last subclass constructor? Alternatively you could call it directly after instantiation.

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();
        }
    }

This will output:

Constructing Super 
Constructing Sub
Constructing SubSub 
Doin' stuff

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM