C#如何在开关中使用枚举


76

我不知道如何结合枚举使用开关。您能否告诉我我在做什么错,以及如何解决?我必须使用一个枚举来制作基本计算器。

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

最终结果应该是这样的:

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

你们能告诉我我怎么搞的吗?

Answers:


116

您不需要转换

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

顺便用括号


4
为什么在这里使用括号?
Stephan Bauer

9
@ J.Starkl好吧,我认为这是一个问题:-)
Stephan Bauer

@StephanBauer:是的,它是:-)
J.Starkl

27
如果您引入了一种新的变量以用于单个情况,那么您当然需要使用方括号。到那时,我的OCD生效了,我需要通过在它们之间添加方括号来使所有情况看起来都一样。(实际上,我在switch语句中使用了括号,因为在其他地方都使用了括号。)
Matthew Watson

9
是的,但是如果您到处使用它们-无陷阱-一致的代码-改进的可读性-简单的维护/扩展-最佳实践(习惯它们)
J.Starkl 2014年


10

已经给出了正确的答案,不过,这是比切换更好的方法:

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

2
我认为这是使用var声明变量的适当示例!
克里斯·邓纳维

1
Var不能在方法主体之外使用。
JustAndrei

2
1.配置和逻辑分离:您的代码变得简短易读。您的配置读起来就像一张桌子,这也很容易。2.与switch不同,Dictionary在内部使用哈希表进行快速查找,这在很多情况下变得很重要。有时,程序员将最常用的项目放在切换的结尾,并且在性能上存在问题。3.从代码中提取配置后,现在您可以做很多很棒的事情:
JustAndrei 2015年

1
A.将其从代码移至外部源,例如配置文件或数据库。B.在执行程序时根据需要动态修改配置。C.创建一个插件系统,以便通过模块扩展您的配置。D.尽管Dictionary已经帮助您更快地搜索键,但是您可以通过自定义查找操作的方式来使其变得更好。一旦我实现了这种替换,就在程序执行过程中累积了案例使用情况统计信息,并定期重新排列了案例列表,以便最受欢迎的案例成为第一个。
JustAndrei

1
我想看到一个可靠的证据,表明Dictionary查找比'用Enums转换更快。
BillW '16


3

您不应该将其转换为整数。对于除法,您需要先向左强制转换为double,否则将进行整数除法。

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

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

1

如果您不想在每种情况下都使用return语句,请尝试以下操作:

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

   return result;
}

除了强制执行项目本地样式约定外,尚不清楚这如何使代码更具可读性。OP的示例代码块是早期返回如何使代码更具可读性的经典示例。
tekHedd

1

所有其他答案都是正确的,但您还需要正确调用方法:

Calculate(5, 5, Operator.PLUS))

而且,由于您使用intleftright,其结果将是int,以及(3/2 will result in 1)。您可以double在计算结果前强制转换为或修改参数以接受double


好吧..是的,有点...:
Stephan Bauer

1

无需转换。您可以在交换机内的枚举上应用条件。像这样

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

然后,这样称呼它:

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

这个答案完美地说明了打破常规并使用1)从函数中提前返回和2)将案例与代码放在同一行的正确时机。
tekHedd

0

两件事情。首先,您需要在测试中对枚举引用进行限定-而不是“ PLUS”,它应该是“ Operator.PLUS”。其次,如果您在开关语句中使用枚举成员名称而不是它们的整数值,那么此代码将更具可读性。我已经更新了您的代码:

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

通过以下方式调用:

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

0

您的代码很好。如果您不确定如何使用Calculate函数,请尝试

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

默认枚举值从0开始,并为以下元素增加1,直到您分配不同的值为止。您也可以:

public enum Operator{PLUS=21,MINUS=345,MULTIPLY=98,DIVIDE=100};
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.