Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Overridden Constructor and Base Constructor in C#

Tags:

c#

constructor

I have two classes, Foo and Bar, that have constructors like this:

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg)
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : base()
    {
      // some third thing
    }
}

Now I want to introduce a constructor for Bar that takes an int, but I want the stuff that happens in Bar() to run as well as the stuff from Foo(int). Something like this:

Bar(int arg) : Bar(), base(arg)
{
  // some fourth thing
}

Is there any way to do this in C#? The best I have so far is putting the work done by Bar() into a function, that also gets called by Bar(int), but this is pretty inelegant.

like image 624
reilly Avatar asked Dec 02 '08 20:12

reilly


People also ask

Can we override base class constructor?

Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. But, a constructor cannot be overridden.

Can a child class call the constructor of a base class?

In Inheritance, the child class acquires the properties of the base class or parent class. You can call the base class constructor from the child class by using the super() which will execute the constructor of the base class. Example: Javascript.

Why overriding is not possible in constructor?

Constructor Overriding is never possible in Java. This is because, Constructor looks like a method but name should be as class name and no return value. Overriding means what we have declared in Super class, that exactly we have to declare in Sub class it is called Overriding.

How do you override a base class property?

you can override properties just like methods. That is, if the base method is virtual or abstract. You should use "new" instead of "override". "override" is used for "virtual" properties.


7 Answers

I would re-chain constructors, so they are called like

Bar() : this(0) 
Bar(int) : Foo(int) initializes Bar
Foo(int) initializes Foo
Foo() : this(0) 

This is suitable, if parameterless constructors are assuming some kind of default value for int parameter of other constructor. If constructors are unrelated, you probably doing something wrong with your type, or maybe we need more information about what are you trying to achieve.

like image 134
Ilya Ryzhenkov Avatar answered Oct 02 '22 09:10

Ilya Ryzhenkov


No, this isn't possible. If you use Reflector to examine the IL that's generated for each constructor, you'll see why -- you'd end up calling both of the constructors for the base class. In theory, the compiler could construct hidden methods to accomplish what you want, but there really isn't any advantage over you doing the same thing explicitly.

like image 44
Curt Hagenlocher Avatar answered Oct 02 '22 11:10

Curt Hagenlocher


I would recommend changing your constructor chain to go from least specific to most specific.

class Foo
{
    Foo()
    {
      // do some stuff
    }

    Foo(int arg): this()
    {
      // do some other stuff
    }
}

class Bar : Foo
{
    Bar() : Bar(0)
    {
      // some third thing
    }

    Bar(int arg): base(arg)
    {
      // something
    }
}

Any creation of the Bar object will now call all 4 constructors. Constructor chaining should provide default values to more specific constructors, not the other way around. You should really look at what you are trying to accomplish and make sure what you are doing makes sense. Curt is right that there are technical reasons you can't do this, but there are also logical reasons why you shouldn't.

like image 30
NerdFury Avatar answered Oct 02 '22 09:10

NerdFury


This is only thing I can think of...

 public class Foo
{
    public Foo()
    {
    }
    public Foo(int? arg): this()
    {
    }

}
public class Bar : Foo
{
    private int x;
    public Bar(): this(new int?()) // edited to fix type ambiguity
    {
        // stuff that only runs for paramerless ctor
    }
    public Bar(int? arg)
        : base(arg)
    {
        if (arg.HasValue)
        {
            // Do stuff for both parameterless and parameterized ctor
        }
        // Do other stuff for only parameterized ctor
    }
}
like image 42
Charles Bretana Avatar answered Oct 02 '22 10:10

Charles Bretana


Can't you have the Bar constructor that takes an int invoke the parameterless constructor?

like image 43
Jim Anderson Avatar answered Oct 02 '22 09:10

Jim Anderson


Can you put the stuff from Bar() in Bar(int) and call Bar(int) with Bar() with a default value? Then Bar(int) can call the base constructor.

class Bar : Foo
{
    Bar() : this(0)
    {
    }

    Bar(int arg) : base(arg)
    {
    }
}

That doesn't exactly answer your question, but depending on your scenario might be a workable solution.

like image 24
g . Avatar answered Oct 02 '22 11:10

g .


can you take the initialization code for Bar() and make it a method and call it from both constructors, and have the new constructor just call base(arg)?

like image 29
CSharpAtl Avatar answered Oct 02 '22 11:10

CSharpAtl