C# 如何在对象构造后执行代码(postconstruction)
正如您在下面的代码中看到的,在构建 Child 对象期间,DoStuff()
方法在 Init()
方法之前被调用。
我现在的情况是,我有很多儿童班。因此,在每个子级构造函数中的 Init()
之后直接重复调用 DoStuff()
方法并不是一个优雅的解决方案。
有什么方法可以在父类中创建某种后置构造函数,该构造函数将在子构造函数之后执行?这样,我就可以调用其中的 DoStuff()
方法。
如果您有任何其他设计想法可以解决我的问题,我也想听听!
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
}
}
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
如果您有复杂的逻辑来构建对象,请考虑 FactoryMethod 模式。
在您的情况下,我会将其实现为一个简单的
方法,该方法接受一些参数,并根据它决定要实例化哪个子类。
您可以从构造函数中删除
DoStuff()
方法调用,并在新实例的Construct()
内部调用它。另外,您应该避免在构造函数中调用虚拟/抽象方法。有关更多详细信息,请参阅此问题:构造函数中的虚拟成员调用
If you have a complex logic for constructing your objects then consider FactoryMethod pattern.
In your case I would implement it as a simple
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 insideConstruct()
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
让我介绍一个使用一些 C# 功能的通用解决方案。请注意,此解决方案不需要您使用工厂模式或在构造对象后调用任何内容,并且它适用于任何类,只需使用单个方法实现接口即可。
首先,我们声明一个我们的类必须实现的接口:
接下来,我们为此接口添加一个静态扩展类,并添加 Initialize 方法:
现在,如果我们需要一个类及其所有后代在该对象之后调用初始化器完全构造完毕后,我们需要做的就是实现
IInitialize
并在构造函数中添加一行:技巧是,当派生类调用扩展方法
Initialize
时,将会抑制任何不是从实际类发出的调用。Let me introduce a general solution using some C# features. Note that this solution does not require you to use a factory pattern or invoke anything after constructing the object, and it works on any class with just implementing an interface with a single method.
First we declare an interface that our classes will have to implement:
Next we add a static extension class for this interface, and add the Initialize method:
Now, if we need a class and all of its descendants to call an initializer right after the object is fully constructed, all we need to do is implement
IInitialize
and append a line in the constructor:The trick is that when a derived class calls the extension method
Initialize
, that will suppress any calls not made from the actual class.这个怎么样:
How about this:
正如其他人提到的,您应该使用工厂模式。
As others have mentioned, you should use a Factory Pattern.
我强烈建议使用 Factory 像模式一样。
如果可能的话:
1。将所有子类和抽象类推入单独的程序集中。
2。像内部方法一样声明子对象的 ctor,因此该程序集中没有人可以仅通过调用 ctor 来构造它们。
3。实现 Factory 类来构造调用者指定的对象类型,这显然会在实际创建对象之后、将其返回给调用者之前强制调用抽象 DoStuff() 方法。
好处是:它还会为您提供额外的抽象级别,因此,如果将来您需要更多的函数调用或任何其他类型的逻辑复杂性,您将需要的是只需将它们添加到您的 Factory 类中即可。
那是。
问候
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
在 WPF 应用程序中,您可以在
Dispatcher
的帮助下推迟DoStuff()
的调用:但是,不保证
DoStuff()
将在构造函数之后立即调用。In WPF applications, you can postpone the invokation of
DoStuff()
with the help ofDispatcher
:However, it is not guaranteed that
DoStuff()
will be called immediately after the constructor.更正:根据此答案,您无法确定在子类构造期间何时调用基类的构造函数。
例如,这不起作用:
所以,是的,正如其他人所指出的,如果事件的顺序很重要,那么基类需要能够通过按顺序声明抽象方法来适应这一点,或者(更好)通过让子类的DoStuff 的实现代表事件的顺序:
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:
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:
DoStuff 是抽象的。只需从 DoStuff 顶部调用 Init 即可。
DoStuff is abstract. Just call Init from the top of DoStuff.
怎么样...
我也尝试过使用
Task.Run
但它工作不可靠。How about...
I also tried with
Task.Run
but that didn't work reliably.您可以尝试:
Rather than using an
abstract
method, which would require you to implement the method in all descendant classes, you might try: