Perché non posso chiamare un costruttore in sé stesso?

4

Attualmente sto eseguendo il porting della classe NumberRange da Java a C #.

Sto scrivendo questo costruttore e mi chiedo se posso chiamare un costruttore in sé. Qualcosa del genere:

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

.NETFiddle

Questo non è un grosso problema, ma sono curioso. Penso che sia per evitare di fare scherzi con il costruttore creando uno Stack Overflow durante la creazione di una classe.

Quindi, perché non posso chiamare un costruttore in sé stesso?

Modifica:

Ricordo che la mia domanda riguardava il "perché" e non il "come". Se ti chiedi come ho implementato questo, leggi il mio codice qui .

    
posta aloisdg 11.09.2015 - 11:44
fonte

5 risposte

1

Il problema sembra non essere la ricorsione, ma con il richiamo del costruttore. Vedi sotto:

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
    }
}

E

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

Ovviamente nel tuo caso la ricorsione era completamente inutile, ma se hai codice che deve essere "ricorsivo" - o semplicemente disponibile al di fuori del contesto di istanziazione di una classe - quel codice deve essere in una funzione non di costruzione.

Vedi questo rispondi al motivo per cui è corretto chiamare i metodi dai costruttori in C #. (In breve, C # gestisce le chiamate al metodo virtuale nei ctors come si potrebbe sperare.)

    
risposta data 11.09.2015 - 12:51
fonte
6

È possibile chiamare un costruttore da un costruttore, ma è necessaria una sintassi diversa e chiamare un costruttore diverso. Ho intenzionalmente cambiato la firma per il costruttore privato per differenziare i due. In questo esempio non va bene poiché dovrebbero avere logicamente la stessa firma

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;
}
    
risposta data 11.09.2015 - 14:42
fonte
-1

Potresti utilizzare tecnicamente Label e goto istruzioni per eseguire essenzialmente la ricorsione senza preoccuparti di 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;
        }
    }
}

Quindi l'esecuzione di quanto segue nella console fa questo:

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

RETURNS 5

nr.Max

RETURNS 10

Questo non risponderà per nulla, ma ho pensato che sarebbe stato utile vedere un'altra versione di 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;
    }
}

Quindi l'esecuzione di quanto segue nella console fa questo:

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

RETURN: 5

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

RETURN: 10

    
risposta data 23.08.2018 - 18:25
fonte
-4

Non puoi chiamare un costruttore dentro se stesso come non puoi chiamare struct nella sua propria struttura, perché quando si chiama uno spazio del costruttore e il valore viene assegnato all'oggetto. Quando il costruttore viene chiamato all'interno del costruttore, continua ad andare in loop, ecco perché hanno proibito una cosa del genere. Anche se sembra facile e possibile non è il caso per tutto il tempo.

    
risposta data 11.09.2015 - 14:59
fonte
-5

EDIT2: Sembra che non sia possibile e mi sono sbagliato. Probabilmente ho confuso due cose che ho fatto in passato. Mi scuso.

Puoi chiamare un costruttore in sé, ma lo chiami scrivendo

new ClassName(arg1, arg2);

piace per iscritto

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

EDIT: Mi dispiace di aver sbagliato su this ();

    
risposta data 11.09.2015 - 11:50
fonte

Leggi altre domande sui tag