Question

I am currently porting the class NumberRange from Java to C#.

I am writing this constructor and I wonder whether I can call a constructor in itself. Something like this:

public NumberRange(Double num1, Double num2)
{
    if (num1 <= num2)
    {
        Min = num1;
        Max = num2;
    }
    else
    {
        NumberRange(num2, num1);
        // Min = num2;
        // Max = num1;
    }
}

.NETFiddle

This is not a big deal, but I am curious. I think it is to prevent messing with constructor by creating a Stack Overflow during a class creation.

So, why can't I call a constructor in itself?

Edit:

I remind that my question was about the "why" and not the "how". If you ask yourself how I implemented this, just read my code here.

Was it helpful?

Solution

The issue seems to be not the recursion, but with invoking the constructor at all. See below:

class NumberRange
{
    public double Min { get; set; }
    public double Max { get; set; }

    public NumberRange(double num1, double num2)
    {
        if (num1 <= num2)
        {
            Min = num1;
            Max = num2;
        }
        else
            NumberRange(num2, num1); // illegal!!
    }

    public void AFunction()
    {
        NumberRange(1, 2); // also illegal!!
        this.NumberRange(1, 2); // 'this' keyword doesn't help
    }
}

And:

new NumberRange(1, 2).NumberRange(2, 1); // can't invoke the constructor on an object either

Obviously in your case the recursion was completely unnecessary, but if you have code which must be "recursable" - or just available outside of the context of instantiating a class - that code must be in a non-constructor function.

See this answer for why it is OK to call methods from constructors in C#. (In short, C# handles virtual method calls in ctors as one might hope.)

OTHER TIPS

You can call a constructor from a constructor but you need a different syntax and to call a different constructor. I intentionally changed the signature for the private constructor to differentiate the two. It isn't good in this example since they should logically have the same signature

public NumberRange(Double num1, Double num2) 
    : this(Math.Min(num1, num2), Math.Max(num1, num2), true) { }
private NumberRange(Double num1, Double num2, bool differentSignature){         
    Min = num1; 
    Max = num2;
}

You could technically use Label and goto statements to essentially run the recursion with out worrying about stackOverflow

class NumberRange {
    public double Min { get; set; }
    public double Max { get; set; }

    public NumberRange(double num1, double num2) {
        DOTHIS:
        if (num1 <= num2) {
            Min = num1;
            Max = num2;
        } else {
            double num = num1;
            num1 = num2;
            num2 = num;
            goto DOTHIS;
        }
    }
}

Then Executing the following at the Console does this:

NumberRange nr = new NumberRange(10, 5);
nr.Min

RETURNS 5

nr.Max

RETURNS 10

This won't at all answer why, but I figured that it would be helpful to see another version of HOW

class NumberRange {
    private double _Min { get; set; }
    private double _Max { get; set; }
    private bool swap { get; set; }
    public double Min {
        get {
            if (!swap) { return _Min; } else { return _Max; }
        }
        set {
            _Min = value;
            if (value <= _Max) { swap = false; } else { swap = true; }
        }
    }
    public double Max {
        get {
            if (swap) { return _Min; } else { return _Max; }
        }
        set {
            _Max = value;
            if (value > _Min) { swap = false; } else { swap = true; }
        }
    }

    public NumberRange(double num1, double num2) {
        Min = num1;
        Max = num2;
    }
}

Then Executing the following at the Console does this:

NumberRange myNumRange_1 = new NumberRange(5, 10);
Console.WriteLine(myNumRange_1.Min + "");

RETURNS: 5

myNumRange_1.Min = 15;
Console.WriteLine(myNumRange_1.Min + "");

RETURNS: 10

You cant call a constructor within itself same as you cant call struct in its own struct, because when you call a constructor space and value get assigned to the object. When constructor is called within the constructor it keeps on looping that's why they prohibited such a thing. Even though it seems easy and possible its not the case for all the time.

EDIT2: It's seems like it's not possible and I was mistaken. Probably confused two things I did in the past. I apologise.

You can call a constructor in itself, but you call it by writing

new ClassName(arg1, arg2);

like in writing

public Constructor(int a1, int a2)
{
    if(a1<a2) return new Class(a2, a1);
}

EDIT: Sorry I was wrong about the this();

Licensed under: CC-BY-SA with attribution
scroll top