C # wie man enum mit switch benutzt

76

Ich kann nicht herausfinden, wie Schalter in Kombination mit einer Aufzählung verwendet werden. Könnten Sie mir bitte sagen, was ich falsch mache und wie ich es beheben kann? Ich muss eine Aufzählung verwenden, um einen Basisrechner zu erstellen.

public enum Operator
{
    PLUS, MINUS, MULTIPLY, DIVIDE
}

public double Calculate(int left, int right, Operator op)
{

    int i = (int) op;

    switch(i)
    {
        case 0:
        {
            return left + right;
        }

        case 1:
        {
            return left - right;
        }

        case 2:
        { 
            return left * right;
        }

        case 3:
        {
            return left / right;
        }

        default:
        {
            return 0.0;
        }
    }
}

Das Endergebnis sollte ungefähr so ​​aussehen:

Console.WriteLine("The sum of 5 and 5 is " + Calculate(5, 5, PLUS))
Output: The sum of 5 and 5 is 10

Könnt ihr mir bitte sagen, wie ich es vermassle?

Jaman
quelle

Antworten:

116

Sie müssen es nicht konvertieren

switch(op)
{
     case Operator.PLUS:
     {
        // your code 
        // for plus operator
        break;
     }
     case Operator.MULTIPLY:
     {
        // your code 
        // for MULTIPLY operator
        break;
     }
     default: break;
}

Verwenden Sie übrigens Klammern

J. Starkl
quelle
4
Warum hier Klammern verwenden?
Stephan Bauer
9
@ J.Starkl Nun, das ist Ansichtssache, denke ich :-)
Stephan Bauer
@StephanBauer: Ja, es ist :-)
J.Starkl
27
Wenn Sie jemals eine neue Variable zur Verwendung in einem Einzelfall einführen, müssen Sie natürlich Klammern verwenden. Und an diesem Punkt setzt meine OCD ein und ich muss dafür sorgen, dass alle Fälle gleich aussehen, indem ich ihnen Klammern hinzufüge. (In aller Ernsthaftigkeit verwende ich Klammern in switch-Anweisungen, weil ich sie überall für Blöcke verwende.)
Matthew Watson
9
Ja, aber wenn Sie sie überall verwenden - keine Fallstricke - konsistenter Code - verbesserte Lesbarkeit - einfachere Wartung / Erweiterung - beste Praxis (gewöhnen Sie sich an sie)
J.Starkl
12

Seit C # 8.0 einen neuen Schalterausdruck für Aufzählungen eingeführt hat, können Sie dies noch eleganter tun:

public double Calculate(int left, int right, Operator op) =>
            op switch 
        {
            Operator.PLUS => left + right,
            Operator.MINUS => left - right,
            Operator.MULTIPLY => left * right,
            Operator.DIVIDE => left / right,
            _    =>  0
        }

Ref. https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8

Przemek Struciński
quelle
10

Die richtige Antwort ist bereits gegeben, dennoch ist hier der bessere Weg (als Schalter):

private Dictionary<Operator, Func<int, int, double>> operators =
    new Dictionary<Operator, Func<int, int, double>>
    {
        { Operator.PLUS, ( a, b ) => a + b },
        { Operator.MINUS, ( a, b ) => a - b },
        { Operator.MULTIPLY, ( a, b ) => a * b },
        { Operator.DIVIDE ( a, b ) => (double)a / b },
    };

public double Calculate( int left, int right, Operator op )
{
    return operators.ContainsKey( op ) ? operators[ op ]( left, right ) : 0.0;
}
JustAndrei
quelle
2
Ich denke, dies ist ein Beispiel dafür, wo die Verwendung von var zum Deklarieren der Variablen angemessen wäre!
Chris Dunaway
1
Var kann nicht außerhalb des Methodenkörpers verwendet werden.
JustAndrei
2
1. Trennung von Konfiguration und Logik: Ihr Code wird kurz und leicht zu lesen. Ihre Konfiguration liest sich wie eine Tabelle, was auch einfach ist. 2. Im Gegensatz zu switch verwendet Dictionary intern eine Hashtabelle für die schnelle Suche. Dies ist in vielen Fällen von Bedeutung. Manchmal setzen Programmierer das am häufigsten verwendete Element am Ende des Schalters und haben Probleme mit der Leistung. 3. Sobald die Konfiguration aus dem Code extrahiert wurde, können Sie jetzt viele großartige Dinge machen:
JustAndrei
1
A. Verschieben Sie es vom Code in eine externe Quelle, z. B. eine Konfigurationsdatei oder Datenbank. B. Ändern Sie die Konfiguration dynamisch an Ihre Bedürfnisse, direkt während der Programmausführung. C. Erstellen Sie ein Plugin-System, damit Ihre Konfiguration um Module erweitert wird. D. Obwohl Dictionary bereits hilft, den Schlüssel schneller zu suchen, können Sie ihn noch verbessern, indem Sie die Art und Weise anpassen, wie Sie den Vorgang nachschlagen. Einmal implementierte ich einen solchen Ersatz für den Switch, der während der Programmausführung Fallnutzungsstatistiken sammelte, und ordnete die Liste der Fälle regelmäßig neu, sodass der beliebteste der erste wurde.
JustAndrei
1
Ich würde gerne einen zuverlässigen Beweis dafür sehen, dass die Suche nach Wörterbüchern schneller ist als "Mit Enums wechseln".
BillW
4

einfach nicht auf int werfen

 switch(operator)
    {
       case Operator.Plus:
       //todo
brennende_LEGION
quelle
3

Sie sollten nicht in eine Ganzzahl umwandeln. Und für die Division müssen Sie zuerst nach links werfen, um zu verdoppeln, wenn nicht, werden Sie eine ganzzahlige Division durchführen.

public enum Operator
{
    PLUS, MINUS, MULTIPLY, DIVIDE
}

public double Calculate(int left, int right, Operator op)
{
    double sum = 0.0;

    switch(op)
    {
       case Operator.PLUS:
       sum = left + right;
       return sum;

       case Operator.MINUS:
       sum = left - right;
       return sum;

       case Operator.MULTIPLY:
       sum = left * right;
       return sum;

       case Operator.DIVIDE:
       sum = (double)left / right;
       return sum;

       default:
       return sum;
   }

   return sum;
}
Jeow Li Huan
quelle
2
 public enum Operator
    {
        PLUS, MINUS, MULTIPLY, DIVIDE
    }

    public class Calc
    {
        public void Calculate(int left, int right, Operator op)
        {

            switch (op)
            {
                case Operator.DIVIDE:
                    //Divide
                    break;
                case Operator.MINUS:
                    //Minus
                    break;
                case Operator.MULTIPLY:
                    //...
                    break;
                case Operator.PLUS:
                    //;;
                    break;
                default:
                    throw new InvalidOperationException("Couldn't process operation: " + op);
            }
        }
    }
omer schleifer
quelle
1

Wenn Sie die return-Anweisung nicht für jeden Fall verwenden möchten, versuchen Sie Folgendes:

Calculate(int left, int right, Operator op)
{
   int result = 0;
   switch(op)
   {
        case Operator.PLUS:
        {
            result = left + right;;  
        }
        break;
        ....
   }

   return result;
}
Martin
quelle
Unklar, wie dies den Code lesbarer macht, außer um projektlokale Konventionen durchzusetzen. Der Beispielcodeblock von OP ist ein klassisches Beispiel dafür, wie eine frühzeitige Rückgabe den Code lesbarer machen kann.
tekHedd
1

Alle anderen Antworten sind korrekt, aber Sie müssen Ihre Methode auch korrekt aufrufen:

Calculate(5, 5, Operator.PLUS))

Und da Sie intfür leftund verwenden right, ist das Ergebnis intauch ( 3/2 will result in 1). Sie können doublevor der Berechnung des Ergebnisses eine Umwandlung vornehmen oder Ihre Parameter so ändern, dass sie akzeptiert werdendouble

Stephan Bauer
quelle
Naja .. ja, irgendwie ... :-D
Stephan Bauer
1

Keine Notwendigkeit zu konvertieren. Sie können Bedingungen für Enums innerhalb eines Switches anwenden. Wie so,

public enum Operator
{ 
    PLUS,
    MINUS,
    MULTIPLY,
    DIVIDE
}

public double Calculate(int left, int right, Operator op)
{
    switch (op)
    {
        case Operator.PLUS: return left + right; 
        case Operator.MINUS: return left - right; 
        case Operator.MULTIPLY: return left * right;
        case Operator.DIVIDE: return left / right;
        default: return 0.0; 
    }
}

Dann nenne es so:

Console.WriteLine("The sum of 5 and 5 is " + Calculate(5, 5, Operator.PLUS));
Kent Aguilar
quelle
Diese Antwort zeigt perfekt den richtigen Zeitpunkt, um die Konvention zu brechen und 1) eine frühzeitige Rückkehr von einer Funktion zu verwenden und 2) den Fall in dieselbe Zeile wie den Code zu setzen.
tekHedd
0

Zwei Dinge. Zunächst müssen Sie die Enum-Referenz in Ihrem Test qualifizieren - anstelle von "PLUS" sollte es "Operator.PLUS" sein. Zweitens wäre dieser Code viel besser lesbar, wenn Sie die Namen der Enum-Mitglieder anstelle ihrer Integralwerte in der switch-Anweisung verwenden würden. Ich habe Ihren Code aktualisiert:

public enum Operator
{
    PLUS, MINUS, MULTIPLY, DIVIDE
}

public static double Calculate(int left, int right, Operator op)
{
    switch (op)
    {
        default:
        case Operator.PLUS:
            return left + right;

        case Operator.MINUS:
            return left - right;

        case Operator.MULTIPLY:
            return left * right;

        case Operator.DIVIDE:
            return left / right;
    }
}

Nennen Sie dies mit:

Console.WriteLine("The sum of 5 and 5 is " + Calculate(5, 5, Operator.PLUS));
Mike
quelle
0

Ihr Code ist in Ordnung. Wenn Sie sich nicht sicher sind, wie Sie die Berechnungsfunktion verwenden sollen, versuchen Sie es

Calculate(5,5,(Operator)0); //this will add 5,5
Calculate(5,5,Operator.PLUS);// alternate

Standard-Enum-Werte beginnen bei 0 und erhöhen sich für folgende Elemente um eins, bis Sie andere Werte zuweisen. Sie können auch:

public enum Operator{PLUS=21,MINUS=345,MULTIPLY=98,DIVIDE=100};
novic3
quelle