2009-10-30 9 views
25

Der Titel ist möglicherweise ein wenig mehrdeutig, aber ich könnte mir keinen besseren Weg vorstellen, dies zu formulieren.Ändern der Parameterwerte vor dem Senden an den Basiskonstruktor

Ich weiß, dass ich einen abgeleiteten Konstruktor vor dem Aufruf eines Basiskonstruktors nicht aufrufen kann, aber kann ich irgendwie Parameterwerte ändern/erstellen, bevor ich sie an die Basis übertrage?

Zum Beispiel

public enum InputType 
{ 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass 
{ 
    public BaseClass(InputType t) 
    { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(value) 
    // Can I do something to infer what value should be here? 
    { 
     // Logic 
    } 
} 

Wenn ich eine abgeleitete Klasse, die den Wert, die für den Basiskonstruktor ableiten kann (in diesem Beispiel InputType.Number gültig wären für ein int,) ist es eine Möglichkeit, zu modifizieren, und/oder Werte erstellen, die an den Basiskonstruktor übergeben werden, bevor der abgeleitete Konstruktor ausgeführt wird?

Antwort

37

Ich erwarte, dass Sie statische Methoden in der Parameterliste des Basisklassenkonstruktors aufrufen können.

public class DerivedClass : BaseClass 
{ 
    public DerivedClass(int i) 
     : base(ChooseInputType(i)) 
    { 
    } 

    private static InputType ChooseInputType(int i) 
    { 
     // Logic 
     return InputType.Number; 
    } 
} 
2

Ja. Es ist in Ordnung, normale Ausdrücke zu verwenden, die nicht auf die Instanz zugreifen, um den Wert zu manipulieren. Zum Beispiel

public DerivedClass(int i) 
    : base((InputType)i) 
{ 
} 
+0

Sie können "Wert" nicht über die Logik im Konstruktor der abgeleiteten Klasse erstellen, da die Basis (...) zuerst ausgeführt wird. –

+0

@Reed, ja das war ein Tippfehler. Es soll eingefügt werden (InputType) i. Behoben – JaredPar

+0

Ja, Sie können casten. Aber er hat nach einer Möglichkeit gefragt, Logik zu verwenden, um Werte zu schaffen, was nicht möglich ist. –

0

No.

Der Basiskonstruktor wird vor jeder Logik im DerivedClass Konstruktor ausgeführt, so gibt es keine Möglichkeit Logik zu injizieren.

Sie können jedoch den Basisklassenkonstruktor ausführen und anschließend im Konstruktor der dervied-Klasse Eigenschaften in der Basisklasse festlegen, um Werte zu ändern.

0

Sie sagen

Ich weiß, dass ich nicht eine abgeleitete Konstruktor vor dem Aufruf einer Basiskonstruktor

nennen kann aber dann zeigen Sie diesen Code

public DerivedClass(int i) 
    : base(value) 
{ 
    // Is it possible to set "value" here? 
    // Logic 
} 

Wenn Sie sich diesen Code Block wird eingegeben, der Basisklassenkonstruktor wurde bereits ausgeführt. Sie können jedoch den Wert in einem Ausdruck ändern, bevor Sie ihn an den Basiskonstruktor übergeben (mit einigen offensichtlichen Einschränkungen). Sie haben jedoch keinen Zugriff auf 'value', es sei denn, es handelt sich um eine Eingabe für den Konstruktor.

+0

Siehe Bearbeiten, ich tippte den Kommentar in die falsche Zeile .. Würde es unter dem Aufruf des Basiskonstruktors eingeben. –

+0

OK, ich sehe, dass andere Ihnen vorgeschlagen haben, dass Sie den Wert ändern können, bevor Sie ihn an den Basiskonstruktor senden. –

3

Sie können eine statische Methode auf abgeleitete Klasse erstellen und Ihre Logik setzen dort:

public enum InputType { 
    Number = 1, 
    String = 2, 
    Date = 3 
} 

public class BaseClass { 
    public BaseClass(InputType t) { 
     // Logic 
    } 
} 

public class DerivedClass : BaseClass { 
    public DerivedClass(int i) 
     : base(GetInputType(i)) { 
     // Is it possible to set "value" here? 
     // Logic 
    } 

    private static InputType GetInputType(Int32 parameter) { 
     // Do something with parameter 
     // and return an InputType 

     return (InputType)Enum.Parse(typeof(InputType), parameter); 
    } 
} 
5

Sie eine statische Methode einen Wert zu berechnen, verwenden kann, um den Basiskonstruktor zu übergeben.

public class DerivedClass : 
    BaseClass 
{ 
    public 
    DerivedClass(int i) : 
     base(ComputedValue(i)) 
    { 
    } 

    public static InputType 
    ComputedValue(int i) 
    { 
     return InputType.Number; // or any other computation you want here 
    } 
} 
1

Ein Hack beliebige Logik in base() Klausel zu setzen, ohne eine separate statische Methode einzuführen, ist eine Lambda oder anonyme Delegaten zu verwenden. Der Ausdruck innerhalb base() ist im Bereich aller Konstruktorparameter, so dass Sie sie innerhalb des Lambda frei verwenden können. Z.B. (Sagen wir, das ist C# 2.0, so gibt es keine LINQ eine Single-Liner für die gleiche Sache zu schreiben):

class Base 
{ 
    public Base(int[] xs) {} 
} 

class Derived : Base 
{ 
    public Derived(int first, int last) 
     : base(
      ((Func<int[]>)delegate 
      { 
       List<int> xs = new List<int>(); 
       for (int x = first; x < last; ++x) 
       { 
        xs.Add(x); 
       } 
       return xs.ToArray(); 
      })()) 
    { 
    } 
} 

Allerdings habe ich stark gegen die Verwendung dieser in der Praxis raten würde, denn von Lesbarkeit Sicht wirklich schrecklich. Bei einer statischen Methode müssen Sie explizit Konstruktorargumente übergeben, aber normalerweise haben Sie nicht mehr als 3-4 davon.

+0

Pavel, gibt es eine Möglichkeit, dies zu tun, wenn die Basisklasse mehr als ein Konstruktorargument benötigt? –

+0

Sie können ein separates Lambda für jedes Argument haben, aber Sie können keine Variablen zwischen diesen Lambdas teilen (außer für Konstruktorargumente). –

+0

Dank Pavel - das ist genau das Problem, das ich versuche zu lösen .. (Freigabe von Variablen zwischen Lambdas). Im Grunde möchte ich eine Logik einkapseln, die einige Berechnungen durchführt und drei verschiedene (aber verwandte) Felder zurückgibt, von denen jedes einen eigenen Parameter für den Konstruktor der Basisklasse initialisiert. Am Ende habe ich damit umgegangen, indem ich zum statischen Methodenansatz (besser lesbar wie gesagt) zurückgekehrt bin, eine Struktur zurückgegeben und die statische Methode einmal für jeden Parameter aufgerufen habe. Es ist hacky, aber funktioniert, da für mein Szenario keine Nebenwirkungen zwischen den Aufrufen der statischen Methode bestehen –

Verwandte Themen