programmernovice
programmernovice

Reputation: 3941

Calling constructor from other constructor in same class at the end

I read here it is possible to call another constructor Calling constructor from other constructor in same class

But it calls the other constructor at the beginning, whereas I want to call at the end. Is this possible ?

Update for people asking for specific: In program.cs I want to be able, depending on some context, to do

either this:

// Form1 will show a message from its own private member
Application.Run(new Form1());

or this:

// Form1 will show a message from class1 member (kind of overloading form1 message if class1 exists)
Application.Run(new Form1(new Class1()));

I Form1 I have

private string member = "Test Sample if no class1";

In class1 I have

private string member = "Test Sample from class1";
public string member;
{
    get { return this.member; }
    set { this.member = value; }
}

In Form1 I have these 2 constructors

// of course Form1() could contain 100 lines of code
Form1() { MessageBox.Show(this.member); }

// I don't want to duplicate 100 lines in second constructor
// so I need to call first constructor
Form1(class1) {
    this.member = class1.member;
    // this is where I would now like to call Form1()
    // but the syntax below doesn't work
    this();
}

Upvotes: 2

Views: 2115

Answers (8)

awe
awe

Reputation: 22460

I don't see why the answers from people here can't be used in your case. And that does not rely on the complexity in your constructor.

There are 2 approaches you can use:

Perfect answer by Pavel Minaev that solves your problem by chaining constructors.
This approach can be used if your call is not "in the middle" of something.

Perfect answer by Christian Hayter that solves your problem by moving common initializing to a separate method that is called in all constructors. That way you can do whatever you like in the different constructors.

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273854

No, the constructor mechanism is very clear and strict, you can only 'call' an other constructor before the one you are writing.

But you could use that to your advantage, just reverse your thinking (approach) to make the 'last' constructor the one the user calls. To work out the specifics, you will have to post some sample code.

Edit:

There are easy workarounds, like:

class Form1
{
   public Form1(Class1 c1)
   {
      if (c1 != null) this.member = c1.member;
   }

   public Form1() : this(null)
   {
   }
}

But you are not allowed to call a constructor form 'inside' another, this would create much more problems.

Upvotes: 7

Christian Hayter
Christian Hayter

Reputation: 31071

In the general case, no. It's not a feature supported either by the C# language or the CLR.

In your specific case, just follow the pattern Microsoft have already given you with the designer code. If it's good enough for them...

public Form1() {
    InitializeComponent();
    InitializeComponentEx();
    MessageBox.Show(this.member);
}

public Form1(T class1) {
    this.member = class1.member;
    InitializeComponent();
    InitializeComponentEx();
}

private void InitializeComponentEx() {
    // my 100 lines of code
}

Upvotes: 2

aaronb
aaronb

Reputation: 2229

The shared logic is placed in the ConstructorFinished method.

Form1() {
  // Call the method to do the logic
  ConstructorFinished();
}



void ConstructorFinished()
{
   MessageBox.Show(this.member);
}



Form1(class1) {
    this.member = class1.member;

    // Call the method to do the logic
    ConstructorFinished();
}

Upvotes: 2

Pavel Minaev
Pavel Minaev

Reputation: 101665

As others have already explained, this just isn't how it works. For your particular case, I would probably do this:

Form1() : this(null)
{
}

Form1(Class1 class1)
{
    if (class1 != null)
    {
        this.member = class1.member;
    }

    ...
    MessageBox.Show(this.member);
    ...
}

Upvotes: 2

Mark Simpson
Mark Simpson

Reputation: 23375

The general solution for this is to put your standard initialisation code in a main constructor, then use the other constructors to pass into it. Since you're only setting a string, you'd do something like this:

private const string DefaultValue = "some default value";
private string member;

Form1() : this(DefaultValue)
{

}

Form1(string overloadedStringAhoy) 
{
    this.member = overloadedStringAhoy;
}

If you call the default constructor (Form1()) you will simply pass through to the overloaded constructor with a default value for the name.

I tend to avoid these kinds of constructors, as complicating them with "oh this has to happen in this order and that won't be set" logic can make maintenance harder. If you encounter this a lot, tread carefully. :)

In this case, it's a trivial setup and the code isn't going to get too complicated and it'll do what you need, so it's OK I guess. If you ever find yourself having to special case + pass through a lot of initialisation code, it's often a lot nicer to use a simple factory or builder class. This way, you keep your class constructor code as simple as possible and leave the wiring to the factory/builder.

Upvotes: 1

Fredrik Mörk
Fredrik Mörk

Reputation: 158409

Not that I am aware of. You should probably move the initialization code that you need to perform last into a separate, private method and have that called from both constructors where appropriate.

Upvotes: 12

user151323
user151323

Reputation:

No, if you use constructor chaining, the base class constructor is always called first.

Upvotes: 7

Related Questions