Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call Constructor Base after Code Execution

Tags:

c#

constructor

Let say we have Class A and Class B. ClassB extends Class A. (ClassB : ClassA)

Now let's say that whenever I instantiate ClassB, I'd like to Run some Random code and only then call "base" to reach ClassA constructor.

Like:

class ClassA
{
    public ClassA()
    {
        Console.WriteLine("Initialization");
    }  
}

class ClassB : ClassA
{
    public ClassB() //: base() 
    {
        // Using :base() as commented above, I would execute ClassA ctor before                                                         //          Console.WriteLine as it is below this line... 
        Console.WriteLine("Before new");
        //base() //Calls ClassA constructor using inheritance
        //Run some more Codes here...
    }
}

In the programming language I usually work with, I can do that, by simply calling super() after Console.WriteLine(); But I cant make it in C#. Is there any other syntax or other way to do that?

like image 501
Gus2014 Avatar asked May 26 '12 05:05

Gus2014


People also ask

How do you call a base class constructor?

To call the parameterized constructor of base class inside the parameterized constructor of sub class, we have to mention it explicitly. The parameterized constructor of base class cannot be called in default constructor of sub class, it should be called in the parameterized constructor of sub class.

Do you have to call base class constructor?

If a class do not have any constructor then default constructor will be called. But if we have created any parameterized constructor then we have to initialize base class constructor from derived class. We have to call constructor from another constructor. It is also known as constructor chaining.

How do you call a base class constructor in C sharp?

Here AreaOfTank() call base class constructor with the parameter r and h. That means Tank() constructor is called and it will initialize the value of Radius and Height in AreaOfTank(). So there is no need for AreaOfTank class to initialize these values.

Does C# automatically call base constructor?

A base class is always instantiated first from the derived class via a call to the default constructor in the base class, UNLESS you change its constructors (see below). C# doesn't care if it is a default constructor or non-default constructor with parameters.


4 Answers

There's a hacky way of doing it using an instance variable initializer:

using System;

class ClassA
{
    public ClassA()
    {
        Console.WriteLine("Initialization");
    }  
}

class ClassB : ClassA
{
    private readonly int ignoreMe = BeforeBaseConstructorCall();

    public ClassB()
    {
    }

    private static int BeforeBaseConstructorCall()
    {
        Console.WriteLine("Before new");
        return 0; // We really don't care
    }
}

class Test
{
    static void Main()
    {
        new ClassB();
    }    
}

The less hacky way of doing it is to rethink how you construct a ClassB to start with. Instead of having clients call the constructor directly, provide a static method for them to call:

public static ClassB CreateInstance()
{
    Console.WriteLine("Before initialization stuff");
    return new ClassB();
}
like image 55
Jon Skeet Avatar answered Oct 19 '22 21:10

Jon Skeet


Another hack if you can get away with calling a static method.

public class ClassA
{
    public ClassA()
    {
        Debug.WriteLine("Call A Constructor");
    }
}

public class ClassB:ClassA
{
    public ClassB():this(aMethod())
    {
    }

    private ClassB(object empty):base()
    {
        Debug.WriteLine("Class B Second Constructor");
    }

    private static object aMethod()
    {
        Debug.WriteLine("Run me First");
        return null;
    }
}
like image 8
Spevy Avatar answered Oct 19 '22 20:10

Spevy


Another elegant solution would be to completely rethink how your objects are constructed. In the constructor of your base class you can call your own construct function, and you omit dependent future constructors, in the following way:

public class ClassA
{
    public ClassA()
    {
        Construct();
    }

    public virtual void Construct()
    {
        Console.WriteLine("3");
    }
}

public class ClassB : ClassA
{
    public override void Construct()
    {
        Console.WriteLine("2");
        base.Construct();
    }
}

public class ClassC : ClassB
{
    public override void Construct()
    {
        Console.WriteLine("1");
        base.Construct();
    }
}
like image 6
PietjePuk Avatar answered Oct 19 '22 20:10

PietjePuk


Actually, you can:

class Foo
{
    public Foo(string s)
    {
        Console.WriteLine("inside foo");
        Console.WriteLine("foo" + s);
    }
}

class Bar : Foo
{
    public Bar(string s) : base(((Func<string>)(delegate ()
    {
        Console.WriteLine("before foo");
        return "bar" + s;
    }))())
    {
        Console.WriteLine("inside bar");
    }
}

class Program
{
    static void Main(string[] args)
    {
        new Bar("baz");
    }
}

Output:

before foo
inside foo
foobarbaz
inside bar

But I will prefer to not use this trick if it is possible.

like image 6
Krypt Avatar answered Oct 19 '22 21:10

Krypt