Throwing exceptions in switch statements when no specified case can be handled

后端 未结 9 1574
你的背包
你的背包 2021-01-30 15:52

Let\'s say we have a function that changes a password for a user in a system in an MVC app.:

public JsonResult ChangePassword
    (string username, string curren         


        
相关标签:
9条回答
  • 2021-01-30 16:15

    I think approaches like this can be very useful (for example, see Erroneously empty code paths). It's even better if you can have that default-throw be compiled away in released code, like an assert. That way you have the extra defensiveness during development and testing, but don't incur the extra code overhead when releasing.

    0 讨论(0)
  • 2021-01-30 16:24

    I always like to do exactly what you have, although I usually throw an ArgumentException if it's an argument that was passed in, but I kind of like NotImplementedException better since the error is likely that a new case statement should be added rather than the caller should change the argument to a supported one.

    0 讨论(0)
  • 2021-01-30 16:29

    For a web application I would prefer a default that generates a result with an error message that asks the user to contact an adminstrator and logs an error rather than throws an exception that might result in something less meaningful to the user. Since I can anticipate, in this case, that the return value might be something other than what I expect I would not consider this truly exceptional behavior.

    Also, your use case that results in the additional enum value shouldn't introduce an error into your particular method. My expectation would be that the use case only applies on login -- which would happen before the ChangePassword method could legally be called, presumably, since you'd want to make sure that the person was logged in before changing their password -- you should never actually see the ContactUs value as a return from the password validation. The use case would specify that if a ContactUs result is return, that authentication fails until the condition resulting in the result is cleared. If it were otherwise, I'd expect that you'd have requirements for how other parts of the system should react under that condition and you'd write tests that would force you to change the code in this method to conform to those tests and address the new return value.

    0 讨论(0)
  • 2021-01-30 16:29

    Validating runtime constraints is usually a good thing, so yes, best practice, helps with 'fail fast' principle and you are halting (or logging) when detecting an error condition rather than continuing silently. There are cases where that is not true, but given switch statements I suspect we do not see them very often.

    To elaborate, switch statements can always be replaced by if/else blocks. Looking at it from this perspective, we see the throw vs do not throw in a default switch case is about equivalent to this example:

        if( i == 0 ) {
    
    
        } else { // i > 0
    
    
        }
    

    vs

        if( i == 0 ) {
    
    
        } else if ( i > 0 ) {
    
    
        } else { 
            // i < 0 is now an enforced error
            throw new Illegal(...)
        }
    

    The second example is usually considered better since you get a failure when an error constraint is violated rather than continuing under a potentially incorrect assumption.

    If instead we want:

        if( i == 0 ) {
    
    
        } else { // i != 0
          // we can handle both positve or negative, just not zero
        }
    

    Then, I suspect in practice that last case will likely appear as an if/else statement. Because of that the switch statement so often resembles the second if/else block, that the throws is usually a best practice.

    A few more considerations are worthwhile: - consider a polymorphic approach or an enum method to replace the switch statement altogether, eg: Methods inside enum in C# - if throwing is the best, as noted in other answers prefer to use a specific exception type to avoid boiler plate code, eg: InvalidEnumArgumentException

    0 讨论(0)
  • 2021-01-30 16:34

    I always throw an exception in this case. Consider using InvalidEnumArgumentException, which gives richer information in this situation.

    0 讨论(0)
  • 2021-01-30 16:37

    I never add a break after a throw statement contained in a switch statement. Not the least of the concerns is the annoying "unreachable code detected" warning. So yes, it is a good idea.

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