2 Stimmen

Überladen einer Methode basierend auf dem Parameterwert?

Ich habe eine Klasse und möchte, dass der Klassenkonstruktor je nach Wert des ersten Parameters variiert.

public class Calc
    {
        public Calc(Operator calcOpr = Operator.Concat, string sourceName, string newString)
        {
            calcOperator = calcOpr;
            sourceType = dataType;
        }

        public Calc(Operator calcOpr = Operator.PadLeft, int startindex, int  count)
        {
            calcOperator = calcOpr;
            sourceType = dataType;
        }

Jetzt WEISS ich, dass der obige Code nicht gültig ist, aber als Pseudocode zeigt er, was ich erreichen möchte.
Gibt es eine Möglichkeit, Klassenkonstruktoren aufgrund der Parameterwerte überladen zu lassen?

EDIT: Ich möchte dies tun, damit die beim Instanziieren der Klasse erforderlichen Parameter je nach verschiedenen Operator-Werten geändert werden.

1voto

Sie könnten es auf diese Weise implementieren:

public class Calc
    {
        public Calc(string sourceName, string newString )
        {
            calcOperator = Operator.Concat;
            sourceType = dataType;
        }

        public Calc(int startindex, int  count )
        {
            calcOperator = Operator.PadLeft;
            sourceType = dataType;
        }
}

1voto

gjvdkamp Punkte 9133

Der Beispielcode ist etwas fehlerhaft, da sie unterschiedliche Signaturen haben (String vs. int für das zweite Argument). Daher würde das Übergeben eines int oder String bereits die richtige Überladung auswählen.

Wenn Sie unterschiedliches Verhalten mit derselben Methodensignatur wünschen, schalten Sie einfach das Enum um:

switch(calcOpr){
  case Operator.Concat: 
    calcOperator = calcOpr;
    sourceType = dataType;
    break;

  case Operator.Padleft: 
    calcOperator = calcOpr;
    sourceType = dataType;
    break;

  default: 
    // Fehler werfen?

}

Bearbeiten (zu Ihrem Edit)

Eine Methode hat eine feste Signatur, daher müssten Sie, wenn Sie einen Konstruktor möchten, der den richtigen Typ basierend auf dem Operator erstellt, alle möglichen Argumente dort angeben. (schlechter Code):

public Calc( Operator calcOpr, string sourceName, string newString,  int startindex, int  count )
{
  switch(calcOpr){
    case Operator.Concat: 
       // Überprüfen von sourceName und newString

    case Operator.Padleft
       // Überprüfen von startindex und count

}

Riecht nicht gut.

Ich würde wohl separate Methoden anstelle von Konstruktorüberladungen verwenden (statisch, damit Sie sie vom Typ aus aufrufen können):

public static Calc GetConcat(string SourceName, string newString){
  Class c = new Class();
  c.calcOperator = Operator.Concat;
  c.sourcetype = dataType; //Woher kommt dieses?
  //etc..
  return c;
}

public static Calc GetPadLeft(int startindex, int  count){
  Class c = new Class();
  c.calcOperator = Operator.PadLeft;
  c.sourcetype = dataType; //Woher kommt dieses?
  // etc
  return c;
}

Sie könnten auch überlegen, abgeleitete Klassen für Concat und PadLeft zu erstellen, die von Calc abgeleitet sind und Methoden überladen oder spezifische Eigenschaften hinzufügen. Eigentlich glaube ich, dass das ist, was ich tun würde, aber Sie müssten ein wenig mehr darüber sagen, was Sie genau tun.

1voto

bruno conde Punkte 47059

Ich denke, dass ein gutes Muster hier wäre, eine Fabrik zu verwenden.

Ein CalcFactory würde den Aufrufern ermöglichen, explizit das konkrete Ziel des Calc zu kennen.

public static class CalcFactory
{
   public static Calc createConcatCalc(string sourceName, string newString)
   {
       // Aufruf expliziter Konstruktoren
   }

   public static Calc createPadLeftCalc(int startindex, int count)
   {
       // Aufruf expliziter Konstruktoren
   }
}

Diese Fabrik könnte intern die Konstruktoren von @Roflcoptr verwenden.

0voto

ferosekhanj Punkte 1076

Vielleicht können Sie es mit einem Konstruktor mit Variablenargumenten versuchen.

public class Calc
{
    public Calc(Operator calcOpr, params object[] values)
    {
        switch (calcOpr)
        {
            case Op.CONCAT:
                Concat(values[0], values[1]);
            case Op.PADLEFT:
                PadLeft(values[0], values[1], values[2]);
        }
    }

    public void Concat(string str1, string str2)
    {
    }
    public void PadLeft(string str1, int startindex, int count)
    {
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X