2010-11-18 12 views
7

ich folgendes Problem habe:Problem mit Konstrukteuren und Vererbung in C#

public class A { 
    public A(X, Y, Z) { 
    ... 
    } 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 
     //i want to instantiate Z here and only then pass it to the base class! 
    } 
} 

Wie kann ich dieses Problem lösen? Gibt es einen Weg?

+0

Was? ist "B: A"? Wenn ja, wie kann A * mehr * Daten als B haben? Außerdem scheint A keinen solchen Konstruktor zu haben ... – Kobi

+0

Meinst du öffentliche Klasse B: A {in deinem Beispiel? –

+0

Bearbeiteter Originalbeitrag. Ja, es ist B: A –

Antwort

13

Die gemeinsame Lösung ist eine statische Methode der Art gehören, zu nennen Das kann den Wert des Parameters berechnen, der an den Basiskonstruktor übergeben werden soll.

Zum Beispiel:

public B(int x, int y) 
    : base(x, y, CalculateZ(x, y)) 
{ 

} 

// You can make this parameterless if it does not depend on X and Y 
private static int CalculateZ(int x, int y) 
{ 
    //Calculate it here. 

    int exampleZ = x + y; 

    return exampleZ; 
} 

Sie beachten Sie, dass CalculateZ keine Instanzmethode sein kann, weil die this Referenz in Konstruktor Initialisierungen nicht verfügbar ist.

Von dem sprach Spezifikation 10.11.1 Constructor initializers:

Ein Instanzkonstruktors initializer kann nicht die Instanz zugreifen erstellt wird. Daher ist es ein Kompilierzeitfehler dieses in einem Argumente Expression des Konstruktor Initialisierer referenzieren, wie es ist, ein Kompilierzeitfehler für ein Argument Ausdruck jede Instanz Element durch einen einfachen Namen zu referenzieren.

BEARBEITEN: In der Beschreibung 'Instanz' in 'statisch' geändert.

+1

+1, aber meinst du nicht, dass es legal ist, * anzurufen statische * Methoden? – LukeH

+0

@Kobi, @LukeH: War ein Gehirn-Freeze-Tippfehler; der Verstand denkt eine Sache und die Finger eine andere. Danke, dass du es aufgezeigt hast. – Ani

1
public abstract class A { 
    public A(X, Y) { 
    ... 
    } 

    public abstract Z TheVariableZ{get;set;} 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 
     //i can only calculate Z here! 
    } 

    public override Z TheVariableZ{//implement it here} 
} 

Und wenn Sie nicht eine abstrakt machen, markieren Sie einfach die Eigenschaft als virtuelle

+3

Das Aufrufen einer virtuellen Methode in einem Konstruktor ist eine schlechte Idee: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

1

Möglicherweise dies:

public abstract class A { 
    public A(X, Y) { 
     CalculateZ(); 
    } 

    abstract void CalculateZ(); 
} 

public class B : A { 
    public B(X, Y) : base(X, Y) { 

    } 

    override void CalculateZ() 
    { 
     ... Calculate here. 
    } 
} 
+3

Eine virtuelle Methode aufrufen in einem Konstruktor ist eine schlechte Idee: http://msdn.microsoft.com/en-us/library/ms182331(v=VS.100).aspx –

2

Sie müssen Z berechnen, bevor der Konstruktor selbst aufgerufen wird. Wenn es einfach ist, können Sie einen Inline-Ausdruck verwenden, sonst müssen Sie eine Hilfsfunktion definieren.

Mit einem helperfunction:

public class A { 
    public A(X x, Y y, Z z) { 
    ... 
    } 
} 

public class B : A { 
    private static Z calculateZ() 
    { 
    } 

    public B(X x, Y y) : base(X, Y, calculateZ()) { 

    } 
} 

Ohne helperfunction:

public B(X, Y) : base(X, Y, X+Y) { 

}