Switch statement without default when dealing with enumerations

后端 未结 10 2361
萌比男神i
萌比男神i 2020-12-15 15:59

This has been a pet peeve of mine since I started using .NET but I was curious in case I was missing something. My code snippet won\'t compile (please forgive the forced nat

相关标签:
10条回答
  • 2020-12-15 16:14

    I realize that this is a thread resurrection...

    I personally feel that the way that switch works is correct, and it operates how I would logically want it to.

    I'm surprised to hear such complaining about the default label.

    If you only have a strict set of enums or values that you are testing, you don't need all of the exception handling lines, or a return outside of the switch, etc.

    Just put the default label over one of the other labels, perhaps the label that would be the most common response. In your example case it probably doesn't matter which one. Short, sweet, and it fulfills your needs to rid of the compiler warning:

    switch (decision)
    {
        default:
        case Decision.Yes:
            return "Yes, that's my decision";
        case Decision.No:
            return "No, that's my decision";
    }
    

    If you don't want the default to be Yes, put the default label above the No label.

    0 讨论(0)
  • 2020-12-15 16:15

    Throw an exception in the default clause:

    default:
        throw new ArgumentOutOfRangeException("decision");
    

    This ensures that all possible paths are covered, while avoiding the logic errors resulting from adding a new value.

    0 讨论(0)
  • 2020-12-15 16:15

    The default is there to protect you. Throw an exception from the default and if anyone adds an extra enum, you're covered with something to flag it.

    0 讨论(0)
  • 2020-12-15 16:23

    Instead of complaining about how the switch statement works, avoid it entirely by using an extension method on the enum as explained here and here.

    The nice thing about this approach is, you don't get into a situation and forgetting to update your GetDecision switch statement when adding a new enum value because it's all together in the same place - in the enum declaration.

    The efficiency of this approach is not known to me and, really, not even a consideration at this point. That's right, I just don't care because it's so much easier for me that I figure, "Phhhtt screw the computer that's what it's there for - to work hard." (I may regret that attitude when Skynet takes over.)

    If I ever need to get from one of those attribute values back to the enum value, I can simply build a reverse dictionary of and fill it with a single line of code.

    (I usually do a 'not set' as the first enum element because, as the OP notes, a C# enum is really an int so an uninitialized variable is going to be zero or the first enum value)

    public enum Decision
    {
      [DisplayText("Not Set")]
      NotSet,
      [DisplayText("Yes, that's my decision")]
      Yes,
      [DisplayText("No, that's my decision")]
      No
    }
    
    public static class XtensionMethods
    {
      public static string ToDisplayText(this Enum Value)
      {
        try
        {
          Type type = Value.GetType();
          MemberInfo[] memInfo =
            type.GetMember(Value.ToString());
    
          if (memInfo != null && memInfo.Length > 0)
          {
            object[] attrs = memInfo[0]
              .GetCustomAttributes(typeof(DisplayText), false);
            if (attrs != null && attrs.Length > 0)
              return ((DisplayText)attrs[0]).DisplayedText;
          }
        }
        catch (Exception ex)
        {
          throw new Exception(
            "Error in XtensionMethods.ToDisplayText(Enum):\r\n" + ex.Message);
        }
        return Value.ToString();
      }
    
      [System.AttributeUsage(System.AttributeTargets.Field)]
      public class DisplayText : System.Attribute
      {
        public string DisplayedText;
    
        public DisplayText(string displayText)
        {
          DisplayedText = displayText;
        }
      }
    }
    

    Use inline like:

    myEnum.ToDisplayText();
    

    Or wrapped in a function, if you feel like it:

    public string GetDecision(Decision decision)
    {
      return decision.ToDisplayText();
    }
    
    0 讨论(0)
提交回复
热议问题