【问题标题】:C# how to use enum with switchC#如何使用带开关的枚举
【发布时间】:2013-02-14 16:18:11
【问题描述】:

我不知道如何将开关与枚举结合使用。你能告诉我我做错了什么,以及如何解决吗?我必须使用枚举来制作基本的计算器。

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

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

【问题讨论】:

    标签: c# enums switch-statement switch-expression


    【解决方案1】:

    你不需要转换它

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

    顺便说一下,用括号

    【讨论】:

    • @J.Starkl 嗯,这是一个见仁见智的问题,我认为 :-)
    • @StephanBauer:是的,它是:-)
    • 我自己更像是一个缩进的人 =) 奇怪的是,这是我唯一没有戴上大括号的东西。去图吧!
    • 如果你曾经引入一个新的变量用于单个案例,你当然需要使用括号。那时我的强迫症开始了,我需要通过添加括号来使所有案例看起来都一样。 (说真的,我在 switch 语句中使用方括号,因为我在其他任何地方都将它们用于块。)
    • 是的,但是如果你在任何地方都使用它们 - 没有陷阱 - 一致的代码 - 提高了可读性 - 更简单的维护/扩展 - 最佳实践(习惯它们)
    【解决方案2】:

    由于 C# 8.0 为枚举引入了新的 switch 表达式,您可以更优雅地做到这一点:

    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
            }
    

    参考。 https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8

    【讨论】:

    • 任何减少花括号需求的语法糖都是好的。
    • 请将其中一个被分割的值转换成double,不要混淆新人,传播错误代码。
    【解决方案3】:

    已经给出了正确的答案,但是这里是更好的方法(比切换):

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

    【讨论】:

    • 我认为这是一个使用 var 来声明变量的例子!
    • Var 不能在方法体之外使用。
    • 1.配置和逻辑分离:你的代码变得简短易读。您的配置读起来像一张桌子,这也很简单。 2. 与switch不同,Dictionary内部使用哈希表进行快速查找,当有很多情况时,这变得很重要。有时程序员将最常用的项目放在切换的末尾,并且会出现性能问题。 3. 一旦配置从代码中提取出来,现在你可以做出很多很棒的事情:
    • A.将其从代码移动到外部源,例如配置文件或数据库。 B. 在程序执行时根据您的需要动态修改配置。 C. 创建一个插件系统,让你的配置被模块扩展。 D. 尽管 Dictionary 已经有助于更快地搜索关键字,但您可以通过自定义查找操作的方式使其变得更好。有一次我为 switch 实现了这样的替换,它在程序执行期间累积了 case 使用统计信息,并定期重新排列 case 列表,以便最受欢迎的一个成为第一个。
    • 我希望看到一个可靠的证据表明字典查找比“使用枚举切换”更快。
    【解决方案4】:

    您不应该转换为整数。对于除法,您需要先将 left 转换为 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;
    }
    

    【讨论】:

      【解决方案5】:

      只是不要转换为 int

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

      【讨论】:

        【解决方案6】:

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

        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)将案例与代码放在同一行的正确时间。
        【解决方案7】:
         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);
                    }
                }
            }
        

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

          • 不清楚这如何使代码更具可读性,而不是强制项目本地样式约定。 OP 的示例代码块是提前返回如何使代码更具可读性的经典示例。
          【解决方案9】:

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

          Calculate(5, 5, Operator.PLUS))
          

          由于您将int 用于leftright,因此结果也将是int (3/2 will result in 1)。您可以在计算结果之前转换为double,或者修改您的参数以接受double

          【讨论】:

          • 嗯..是的,有点... :-D
          【解决方案10】:

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

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

          【讨论】:

            【解决方案11】:

            您的代码很好。如果您不确定如何使用计算功能,请尝试

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-02-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多