Reputation: 437
I implemented the following structure:
public abstract class A
{
protected A()
{
Test();
}
private void Test()
{
Console.WriteLine("2");
}
}
public class B : A
{
public B() : base()
{
Console.WriteLine("1");
}
}
When I create an instance of class B
, the method Test()
is executed before the constructor calls in class B
. In my case, this method should run after the child is fully initialized. A possible way to make it work would be to make Test()
accessible from B
and call it at the end of its constructor. That would work but if someone creates another subclass of A
, there is a chance that he forgets to call the method. My question is whether there is a more general solution in the base class to make sure that the method is executed after a child is fully initialized.
Upvotes: 3
Views: 1399
Reputation: 1
I know this is a bit old, but I too wanted to create a base class where it would call code in the constructor after a child class had been initialized. This is because there was a common method that should be called on the base class after the child class initialization, but I did not want to depend on someone who might implement a child class to remember to call this common method (or even have direct access to it).
So I added an action delegate as a parameter in the base class constructor, and in the child class constructor I put initialization logic in a lambda statement and pass it to the base constructor as the action delegate.
Using your example, it looks something like this:
public abstract class A
{
protected A(Action<A> init)
{
init(this); //initialize child class
Test(); //common method to call after child class initialization
}
protected void Test()
{
Console.WriteLine("2");
}
}
public class B : A
{
public int I { get; private set; }
public B(int i) : base(a =>
{
B b = (B)a; //cast base class object to this class
b.I = i; //set fields, properties, etc.
Console.WriteLine("1");
})
{
//do anything else that can occur after base class constructor
}
}
Creating a new instance of B results in this output:
1
2
Upvotes: 0
Reputation: 790
You can't directly "insert" a method call before calling constructor of base class, because it's calling a method on an uninitialized object. But you can use the template method pattern:
abstract class A {
protected A () {
BeforeTest ();
Test ();
}
protected abstract void BeforeTest ();
private void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void BeforeTest () {
Console.WriteLine ("1");
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Alternatively, you can make Test
method virtual:
abstract class A {
protected A () {
Test ();
}
protected virtual void Test () {
Console.WriteLine ("2");
}
}
class B : A {
protected override void Test () {
Console.WriteLine ("1");
base.Test ();
}
}
internal class Program {
public static void Main (string [] args) {
new B ();
}
}
Both examples outputs the same result:
1
2
Upvotes: 1
Reputation: 77886
That can't be done cause constructor initializer doesn't work that way. Rather you can choose to pass some parameter to base constructor, parameters which may be specific to your child class like
public abstract class A
{
protected A(string data)
{
Test(data);
}
private void Test(string data)
{
Console.WriteLine(data);
}
}
public class B : A
{
public B() : base("1")
{
//some other initialization logic here
}
}
Upvotes: 2
Reputation: 391446
The answer is no.
There is nothing built into .NET or C# that can make sure methods are being called after all descendant constructors have executed.
A different approach would be some form of the factory pattern, where your class would basically just provide you with another instance that has been correctly set up, and all required methods called.
Upvotes: 2