Should switch statements always contain a default clause?

匿名 (未验证) 提交于 2019-12-03 08:33:39

问题:

In one of my first code reviews (a while back), I was told that it's good practice to include a default clause in all switch statements. I recently remembered this advice but can't remember what the justification was. It sounds fairly odd to me now.

  1. Is there a sensible reason for always including a default statement?

  2. Is this language dependent? I don't remember what language I was using at the time - maybe this applies to some languages and not to others?

回答1:

Switch cases should almost always have a default case.

Reasons to use a default

1.To 'catch' an unexpected value

switch(type) {     case 1:         //something     case 2:         //something else     default:         // unknown type! based on the language,         // there should probably be some error-handling         // here, maybe an exception } 

2. To handle 'default' actions, where the cases are for special behavior.

You see this a LOT in menu-driven programs and bash shell scripts. You might also see this when a variable is declared outside the switch-case but not initialized, and each case initializes it to something different. Here the default needs to initialize it too so that down the line code that accesses the variable doesn't raise an error.

3. To show someone reading your code that you've covered that case.

variable = (variable == "value") ? 1 : 2; switch(variable) {     case 1:         // something     case 2:         // something else     default:         // will NOT execute because of the line preceding the switch. } 

This was an over-simplified example, but the point is that someone reading the code shouldn't wonder why variable cannot be something other than 1 or 2.


The only case I can think of to NOT use default is when the switch is checking something where its rather obvious every other alternative can be happily ignored

switch(keystroke) {     case 'w':         // move up     case 'a':         // move left     case 's':         // move down     case 'd':         // move right     // no default really required here } 


回答2:

I would always use a default clause, no matter what language you are working in.

Things can and do go wrong. Values will not be what you expect, and so on.

Not wanting to include a default clause implies you are confident that you know the set of possible values. If you believe you know the set of possible values then, if the value is outside this set of possible values, you'd want to be informed of it - it's certainly an error.

That's the reason why you should always use a default clause and throw an error, for example in Java:

switch (myVar) {    case 1: ......; break;    case 2: ......; break;    default: throw new RuntimeException("unreachable"); } 

There's no reason to include more information than just the "unreachable" string; if it actually happens, you're going to need to look at the source and the values of the variables etc anyway, and the exception stacktrace will include that line number, so no need to waste your time writing more text into the exception message.



回答3:

No.

What if there is no default action, context matters. What if you only care to act on a few values?

Take the example of reading keypresses for a game

switch(a) {    case 'w':      // Move Up      break;    case 's':      // Move Down      break;    case 'a':      // Move Left      break;    case 'd':      // Move Right      break; } 

Adding:

default: // Do nothing 

Is just a waste of time and increases the complexity of the code for no reason.



回答4:

NOT having the default case can actually be beneficial in some situations.

If your switch cases are enums values, by not having a default case, you can get a compiler warning if you are missing any cases. That way, if new enum values are added in the future and you forget to add cases for these values in the switch, you can find out about the problem at compile time. You should still make sure the code takes appropriate action for unhandled values, in case an invalid value was cast to the enum type. So this may work best for simple cases where you can return within the enum case rather than break.

enum SomeEnum {     ENUM_1,     ENUM_2,     // More ENUM values may be added in future };  int foo(SomeEnum value) {     switch (value)     {     case ENUM_1:         return 1;     case ENUM_2:         return 2;     }     // handle invalid values here     return 0;  } 


回答5:

In my company, we write software for the Avionics and Defense market, and we always include a default statement, because ALL cases in a switch statement must be explicitly handled (even if it is just a comment saying 'Do nothing'). We cannot afford the software just to misbehave or simply crash on unexpected (or even what we think impossible) values.

It can be discussed that a default case is not always necessary, but by always requiring it, it is easily checked by our code analyzers.



回答6:

Should a "switch" statement always include a default clause? No. It should usually include a default.

Including a default clause only makes sense if there's something for it to do, such as assert an error condition or provide a default behavior. Including one "just because" is cargo-cult programming and provides no value. It's the "switch" equivalent of saying that all "if" statements should include an "else".

Here's a trivial example of where it makes no sense:

void PrintSign(int i) {     switch (Math.Sign(i))     {     case 1:         Console.Write("positive ");         break;     case -1:         Console.Write("negative ");         break;     default: // useless     }     Console.Write("integer"); } 

This is the equivalent of:

void PrintSign(int i) {     int sgn = Math.Sign(i);     if (sgn == 1)         Console.Write("positive ");     else if (sgn == -1)         Console.Write("negative ");     else // also useless     {     }     Console.Write("integer"); } 


回答7:

As far as i see it the answer is 'default' is optional, saying a switch must always contain a default is like saying every 'if-elseif' must contain a 'else'. If there is a logic to be done by default, then the 'default' statement should be there, but otherwise the code could continue executing without doing anything.



回答8:

I would say it depends on the language, but in C if you're switching on a enum type and you handle every possible value, you're probably better off NOT including a default case. That way, if you add an additional enum tag later and forget to add it to the switch, a competent compiler will give you a warning about the missing case.



回答9:

Having a default clause when it's not really needed is Defensive programming This usually leads to code that is overly complex because of too much error handling code. This error handling and detection code harms the readability of the code, makes maintenance harder, and eventually leads to more bugs than it solves.

So I believe that if the default shouldn't be reached - you don't have to add it.

Note that "shouldn't be reached" means that if it reached it's a bug in the software - you do need to test values that may contain unwanted values because of user input, etc.



回答10:

If you know that the switch statement will only ever have a strict defined set of labels or values, just do this to cover the bases, that way you will always get valid outcome.. Just put the default over the label that would programmatically/logically be the best handler for other values.

switch(ResponseValue) {     default:     case No:         return false;     case Yes;         return true; } 


回答11:

Atleast it is not mandatory in Java. According to JLS, it says atmost one default case can be present. Which means no default case is acceptable . It at times also depends on the context that you are using the switch statement. For example in Java, the following switch block does not require default case

private static void switch1(String name) {     switch (name) {     case "Monday":         System.out.println("Monday");         break;     case "Tuesday":         System.out.println("Tuesday");         break;     } } 

But in the following method which expects to return a String, default case comes handy to avoid compilation errors

    private static String switch2(String name) {     switch (name) {     case "Monday":         System.out.println("Monday");         return name;      case "Tuesday":         System.out.println("Tuesday");         return name;      default:         return name;     } } 

though you can avoid compilation error for the above method without having default case by just having a return statement at the end, but providing default case makes it more readable.



回答12:

You should have a default to catch un-expected values coming in.

However, I disagree with the Adrian Smith that your error message for default should be something totally meaningless. There may be an un-handled case you didn't forsee (which is kind of the point) that your user will end up seeing and a message like "unreachable" is entirely pointless and doesn't help anyone in that situation.

Case in point, how many times have you had an utterly meaningless BSOD? Or a fatal exception @ 0x352FBB3C32342?



回答13:

It is an optional coding 'convention'. Depending on the use is whether or not it is needed. I personally believe that if you do not need it it shouldn't be there. Why include something that won't be used or reached by the user?

If the case possibilities are limited (i.e. a Boolean) then the default clause is redundant!



回答14:

If there is no default case in a switch statement, the behavior can be unpredictable if that case arises at some point of time, which was not predictable at development stage. It is a good practice to include a default case.

switch ( x ){   case 0 : { - - - -}   case 1 : { - - - -} }  /* What happens if case 2 arises and there is a pointer * initialization to be made in the cases . In such a case , * we can end up with a NULL dereference */ 

Such a practice can result in a bug like NULL dereference, memory leak as well as other types of serious bugs.

For example we assume that each condition initializes a pointer. But if default case is supposed to arise and if we don’t initialize in this case, then there is every possibility of landing up with a null pointer exception. Hence it is suggested to use a default case statement, even though it may be trivial.



回答15:

Because MISRA C says so:

The requirement for a final default clause is defensive programming. This clause shall either take appropriate action or contain a suitable comment as to why no action is taken.

That said, I recommend against following MISRA C on this, for most software:



回答16:

Depends on how the switch in particular language works, however in most languages when no case is matched, the execution falls through the switch statement without warning. Imagine you expected some set of values and handled them in switch, however you get another value in the input. Nothing happens and you don't know nothing happened. If you caught the case in default, you would know there was something wrong.



回答17:

If the switch value (switch(variable)) can't reach the default case, then default case is not at all needed. Even if we keep the default case, it is not at all executed. It is dead code.



回答18:

The default case may not necessary in the switch used by enum. when switch contained all value, the default case will never execute. So in this case, it is not necessary.



回答19:

Should switch statements always contain a default clause ? No switch cases can exist with out default case, in switch case default case will trigger switch value switch(x) in this case x when not match with any other case values.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!