C# How to execute code after object construction (

2019-02-16 03:53发布

As you can see in the code below, the DoStuff() method is getting called before the Init() one during the construction of a Child object.

I'm in a situation where I have numerous child classes. Therefore, repeating a call to the DoStuff() method directly after Init() in the constructor of each child wouldn't be an elegant solution.

Is there any way I could create some kind of post constructor in the parent class that would be executed after the child's constructor? This way, I could call to the DoStuff() method there.

If you have any other design idea which could solve my problem, I'd like to hear it too!

abstract class Parent
{
    public Parent()
    {
        DoStuff();
    }

    protected abstract void DoStuff();
}

class Child : Parent
{
    public Child()
    // DoStuff is called here before Init
    // because of the preconstruction
    {
        Init();
    }

    private void Init()
    {
        // needs to be called before doing stuff
    }

    protected override void DoStuff() 
    {
        // stuff
    }
}

9条回答
霸刀☆藐视天下
2楼-- · 2019-02-16 04:28

DoStuff is abstract. Just call Init from the top of DoStuff.

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-02-16 04:30

How about this:

abstract class Parent
{
    public Parent()
    {
        Init();
        DoStuff();
    }

    protected abstract void DoStuff();
    protected abstract void Init();
}

class Child : Parent
{
    public Child()
    {
    }

    protected override void Init()
    {
        // needs to be called before doing stuff
    }

    protected override void DoStuff() 
    {
        // stuff
    }
}
查看更多
成全新的幸福
4楼-- · 2019-02-16 04:30

In WPF applications, you can postpone the invokation of DoStuff() with the help of Dispatcher:

abstract class Parent
{
    public Parent()
    {
        Dispatcher.CurrentDispatcher.BeginInvoke(new Action(this.DoStuff));
    }

    private void DoStuff()
    {
        // stuff, could also be abstract or virtual
    }
}

However, it is not guaranteed that DoStuff() will be called immediately after the constructor.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-02-16 04:38

If you have a complex logic for constructing your objects then consider FactoryMethod pattern.

In your case I would implement it as a simple

public static Parent Construct(someParam)

method that takes some parameter and based on it decides which child class to instantiate. You can remove your DoStuff() method call from the constructor and call it inside Construct() on the new instance.

Also, you should avoid virtual/abstract method calls in the constructors. See this question for more details: Virtual member call in a constructor

查看更多
Bombasti
6楼-- · 2019-02-16 04:42

I would strongly suggest use Factory like a pattern.

If it's possible:

1. Push all your childs and abstract class into separate assembly.

2. Declare ctors of childs like internal methods, so no one out of that assembly is can construct them just by calling ctor.

3. Implement the Factory class to construct for caller specified objects type, which obviuoly will forse calling of abstract DoStuff() method after actual creation of anobject, but before returning it to caller.

Good thing about this is that: It will give you also additional level of abstraction, so if in the future you will need some more functions call or any other type of logical complexity, what you will need, is just add them into your Factory class.

That is.

Regards

查看更多
Viruses.
7楼-- · 2019-02-16 04:43

Correction: As per this answer, you can't determine when the base class's constructor is invoked during construction of the subclass.

E.g. This doesn't work:

public Child()
// DoStuff is called here after Init
// because of the overridden default constructor
{
    Init();
    base();
} 

So, yes, as others have noted, if sequence of events matters, then the base class needs to be able to accommodate that by declaring abstract methods in order, or (better yet) by having the child class's implementation of DoStuff represent the sequence of events:

protected override void DoStuff()
{
    Init();
    base.DoStuff();
}
查看更多
登录 后发表回答