【问题标题】:Why do "Not all code paths return a value" with a switch statement and an enum?为什么“并非所有代码路径都返回值”带有 switch 语句和枚举?
【发布时间】:2011-01-05 11:51:07
【问题描述】:

我有以下代码:

public int Method(MyEnum myEnum)
{
    switch (myEnum)
    {
        case MyEnum.Value1: return 1;
        case MyEnum.Value2: return 2;
        case MyEnum.Value3: return 3;
    }
}

public enum MyEnum
{
    Value1,
    Value2,
    Value3
}

我得到了错误:"Not all code paths return a value"。我不明白switch 语句怎么不能跳转到指定的情况之一。

enum 可以以某种方式成为null 吗?

【问题讨论】:

    标签: c# .net visual-studio-2008 c#-3.0 enums


    【解决方案1】:

    没有什么可以说myEnum 的值将是这些值之一。

    不要将枚举误认为是一组限制性值。它实际上只是一组 命名 值。例如,我可以调用你的方法:

    int x = Method((MyEnum) 127);
    

    你想让它做什么?如果你希望它抛出异常,你可以在默认情况下这样做:

    switch (myEnum)
    {
        case MyEnum.Value1: return 1;
        case MyEnum.Value2: return 2;
        case MyEnum.Value3: return 3;
        default: throw new ArgumentOutOfRangeException();
    }
    

    如果您想在 switch 语句之前做一些其他工作,您也可以预先使用Enum.IsDefined。这有拳击的缺点......有一些方法可以解决这个问题,但它们通常更有效......

    示例:

    public int Method(MyEnum myEnum)
    {
        if (!IsDefined(typeof(MyEnum), myEnum)
        {
            throw new ArgumentOutOfRangeException(...);
        }
        // Adjust as necessary, e.g. by adding 1 or whatever
        return (int) myEnum; 
    }
    

    这假设MyEnum 中的基础值与您要返回的值之间存在明显关系。

    【讨论】:

    • @JonSkeet:您能否举个例子说明在这种情况下如何避免拳击?提前致谢。
    • @RaheelKhan:例如,请参阅code.google.com/p/unconstrained-melody
    • 为了任何可能被误导的人,请注意 Jon 对 "use Enum.IsDefined upfront" 的替代建议不会使编译错误消失;即使编译器原则上应该能够找出你已经详尽地覆盖了所有可能的枚举值,只要你在那里有一个IsDefined 签入,它并不聪明足以真正做到这一点。虽然,由于类似的聪明的编译器技巧现在开始得到实现——比如 TypeScript 的类型保护——也许我们会看到编译器变得足够聪明,可以在几年内解决这个问题。
    • @MarkAmery:通过调用Enum.IsDefined,您可以在之后进行投射,而不是使用开关/案例。
    • @JonSkeet 我不明白你的回复,可能是因为我是一个大笨蛋,只是在 C# 中找到自己的脚。将什么投射到什么,以及如何避免开关/案例? myEnum 已经是 MyEnum 类型,那么强制转换有什么帮助呢?也许在你的答案中添加一个你所建议的例子会有所帮助,或者我只是绝望地厚。
    【解决方案2】:
    MyEnum blah = 0;
    

    默认值始终为 0,并且可以隐式转换,即使您没有一个值为 0 的值。

    【讨论】:

      【解决方案3】:

      必须是:

      public int Method(MyEnum myEnum)
      {
          switch (myEnum)
          {
              case MyEnum.Value1: return 1;
              case MyEnum.Value2: return 2;
              case MyEnum.Value3: return 3;
              default: return 0;
          }
      }
      

      或:

      public int Method(MyEnum myEnum)
      {
          switch (myEnum)
          {
              case MyEnum.Value1: return 1;
              case MyEnum.Value2: return 2;
              case MyEnum.Value3: return 3;
          }
      
          return 0;
      }
      

      【讨论】:

      • 或者你可以在枚举不是有效值的情况下抛出异常,或者他想要的任何其他处理情况。
      【解决方案4】:

      枚举不限于它们所代表的值。你可以分配这个:

      MyEnum v = (MyEnum)1000;
      

      而且完全没有问题。为您的开关添加一个默认值,您将处理所有可能的情况。

      【讨论】:

        【解决方案5】:

        如果您更改枚举中的值(添加第四个),您的代码将会中断。你应该在你的 switch 语句中添加一个 default: case。

        当然,实现此目的的另一种方法是在枚举中定义整数值...

        public enum MyEnum
        {
            Value1 = 1,
            Value2 = 2,
            Value3 = 3
        }
        

        然后将您的枚举转换为代码中的 int。您可以使用 int myInt = (int)myEnum 而不是 int myInt = Method(myEnumValue);

        【讨论】:

        • 我的代码如果我改变它就会中断,这不是编译器的事情吗?
        • 不直接,不,但是如果您将我的答案与下面列出的其他人一起扩展,您会看到问题。底线 -> 为代码添加默认情况。
        • 尽管我希望添加枚举值会破坏我的代码,但事实并非如此。
        • 回应传真所说的,如果我向枚举添加一个值并且不向基于该枚举的开关添加大小写,我希望我的代码失败编译。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-17
        相关资源
        最近更新 更多