Is there a way to get the C# compiler to emit an error if a switch(enum_val) is missing a case statement?

前端 未结 8 1870
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-06 04:27

I just realized I added a value to the list of \"must-handle\" values in my enum, but I didn\'t catch it until runtime. I know the C# compiler is really powerful when it com

相关标签:
8条回答
  • 2020-12-06 04:50

    The C# compiler doesn't have this check built-in, but there's a code contracts checker for .Net that does: https://blogs.msdn.microsoft.com/francesco/2014/09/12/how-to-use-cccheck-to-prove-no-case-is-forgotten/

    The technique is to use a code contract assertion to tell the checker that the default case should never be reachable:

    switch (c) {
      case Colors.Red: break;
      case Colors.Blue:
      case Colors.Green: break;
      default:
        Contract.Assert(false); // Tell static checker this shouldn't happen
    }
    

    Then, if the checker sees that it is reachable (because one of the enum values is not handled), it will warn you:

    warning : CodeContracts: This assert, always leading to an error, may be reachable.
    Are you missing an enum case?
    
    0 讨论(0)
  • 2020-12-06 04:53

    You can use SwitchEnumAnalyzer to get compiler-time warnings of this kind. I just used it in my project and it works nicely. As in any Roslyn analyzer, you can choose level of notification - if it should be just warning, or a proper error.

    0 讨论(0)
  • 2020-12-06 04:56

    This is exactly best example why we need Testing in all solutions. You have to write a test that can enumerate your Enum and call that method which contains the switch case. With this test you will get a failed test every time you edit the Enum but forget to update the switch case.

        [Test]
        public void CheckThatAllEnumCoveredInSwitchCase()
        {
    
            foreach (var singleEnum in Enum.GetValues(typeof(YOURENUM)))
            {
                    myclass.methodofswitchcase((YOURENUM)singleEnum);
            }
    
        }
    
    0 讨论(0)
  • 2020-12-06 05:02

    For C++ you can get the compiler to issue a warning by adding the compiler switch /we4061 to your project settings. Hope this helps. :)

    http://msdn.microsoft.com/en-us/library/thxezb7y.aspx

    http://msdn.microsoft.com/en-us/library/96f5t7fy(v=vs.80).aspx

    Actually I was mistaken about this; it appears you can have the compiler throw an error. Just compile with /Wall /we4061. I haven't tried this myself, but from reading the above MSDN pages, it looks like this should work.

    0 讨论(0)
  • 2020-12-06 05:04

    Just by throwing (pun unintended) this out, you can replace the Switch-Case with a dictionary (Func<int,int> as an example):

    Dictionary<Colors,Func<int,int>> d = new Dictionary<Colors, Func<int, int>>();
    d.Add(Colors.Red, (x) => x+1);
    d.Add(Colors.Blue, (x) => x+1);
    d.Add(Colors.Green, (x) => x+1);
    foreach (Colors color in Enum.GetValues(typeof(Colors)))
    {
        if (!d.ContainsKey(color))
        {
            throw new Exception("Poor color " + color + " ignored");
        }
    }
    
    0 讨论(0)
  • 2020-12-06 05:11

    You could throw an exception early on if the enum size, hopefully alerting you very early on when a change to the enum has been made:

    enum MyEnum {A, B};
    
    class TestEnum
    {
        // Static constructor
        static TestEnum()
        {
            // Check if this code needs updating as the enum has changed
            if (Enum.GetNames(typeof(MyEnum)).Length != 2)
            {
                // If this fails update myFunction and the number above
                throw new Exception("Internal error - code inconsistency");
            }
        }
    
        // My function that switches on the enum
        string myFunction(MyEnum myEnum)
        {
            switch (myEnum)
            {
                case MyEnum.A: return "A";
                case MyEnum.B: return "B";
            }
            throw new Exception("Internal error - missing case");
        }
    }
    

    This will throw an exception from the static constructor if the number of items in the enum is changed. So the developer knows he needs to update the code. You could even do this check from a unit test that you run with your build.

    0 讨论(0)
提交回复
热议问题