Call overridden constructor and base constructor in C #

I have two classes: Foo and Bar, which have such constructors:

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 accepts int, but I want the stuff that happens in Bar () to run the same way as stuff from Foo (int). Something like that:

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

Is there any way to do this in C #? The best I'm still doing is making Bar () work as a function, which is also called by Bar (int), but it's rather inelegant.

+49
constructor c #
Dec 02 '08 at 20:21
source share
8 answers

No, It is Immpossible. If you use the Reflector to check the IL generated for each constructor, you will understand why - you end up calling both constructors for the base class. Theoretically, the compiler could build hidden methods to accomplish what you want, but there really is no advantage to doing the same explicitly.

+23
Dec 02 '08 at 20:29
source share

I would re-create the constructors, so they are called as

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

This is suitable if constructors without parameters accept some default value for the int parameter of another constructor. If the constructors are not related to each other, you are probably doing something wrong with your type, or maybe we need more information about what you are trying to achieve.

+32
Dec 02 '08 at 20:29
source share

I would recommend changing the chain of constructors to move from the least specific to the 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. The constructor chain should provide default values ​​for more specific constructors, and not vice versa. You should really look at what you are trying to accomplish, and make sure what you are doing makes sense. Kurt is right that there are technical reasons why you cannot do this, but there are also logical reasons why you shouldn't.

+12
Dec 02 '08 at 20:33
source share

This is the 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 } } 
+3
Dec 02 '08 at 20:32
source share

You don't have a Bar constructor that accepts an int, calls a constructor without parameters?

+1
Dec 02 '08 at 20:27
source share

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

 class Bar : Foo { Bar() : this(0) { } Bar(int arg) : base(arg) { } } 

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

+1
Dec 02 '08 at 20:29
source share

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

+1
Dec 02 '08 at 20:38
source share

You can use this code:

 public Foo { public Foo() { this.InitializeObject(); } public Foo(int arg) : this() { // do something with Foo arg } protected virtual void InitializeObject() { // initialize object Foo } } public Bar : Foo { public Bar : base() { } public Bar(int arg) : base(arg) { // do something with Bar arg } protected override void InitializeObject() { // initialize object Bar base.InitializeObject(); } } 

Just override the InitializeObject() method, as in the above code, and put all your code that you want to place in the constructor without parameters. Finally, type base.InitializeObject() at the end of the code.

Hope this is helpful.

0
Apr 30 '13 at 2:45
source share



All Articles