Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Switch statement without default when dealing with enumerations

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 nature of the sample) because (according to the compiler) a return statement is missing:

public enum Decision { Yes, No}      public class Test     {         public string GetDecision(Decision decision)         {             switch (decision)             {                 case Decision.Yes:                     return "Yes, that's my decision";                 case Decision.No:                     return "No, that's my decision";              }         }     } 

Now I know I can simply place a default statement to get rid of the complier warning, but to my mind not only is that redundant code, its dangerous code. If the enumeration was in another file and another developer comes along and adds Maybe to my enumeration it would be handled by my default clause which knows nothing about Maybes and there's a really good chance we're introducing a logic error.

Whereas, if the compiler let me use my code above, it could then identify that we have a problem as my case statement would no longer cover all the values from my enumeration. Sure sounds a lot safer to me.

This is just so fundamentally wrong to me that I want to know if its just something I'm missing, or do we just have to be very careful when we use enumerations in switch statements?

EDIT: I know I can raise exceptions in the default or add a return outside of the switch, but this are still fundamentally hacks to get round a compiler error that shouldn't be an error.

With regards an enum really just being an int, that's one of .NET's dirty little secrets which is quite embarassing really. Let me declare an enumeration with a finite number of possibilities please and give me a compilation for:

Decision fred = (Decision)123; 

and then throw an exception if somebody tries something like:

int foo = 123; Decision fred = (Decision)foo; 

EDIT 2:

A few people have made comments about what happens when the enum is in a different assembly and how this would result in problems. My point is that this is the behaviour I think should happen. If I change a method signature this will lead to issues, my premis is that changing an enumeration should be this same. I get the impression that a lot of people don't think I understand about enums in .NET. I do I just think that the behaviour is wrong, and I'd hoped that someone might have known about some very obscure feature that would have altered my opinion about .NET enums.

like image 224
Mark Avatar asked Jul 08 '09 15:07

Mark


People also ask

Can you use a switch statement without default?

No it is not necessary of default case in a switch statement and there is no rule of keeping default case at the end of all cases it can be placed at the starting andd middle of all other cases.

Is default mandatory for switch case?

The default statement is optional and can appear anywhere inside the switch block. In case, if it is not at the end, then a break statement must be kept after the default statement to omit the execution of the next case statement.

Is default optional in switch case?

3) The default statement is optional. Even if the switch case statement do not have a default statement, it would run without any problem.

Is default necessary in switch case PHP?

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'.


2 Answers

Heck, the situation is far worse than just dealing with enums. We don't even do this for bools!

public class Test {           public string GetDecision(bool decision) {     switch (decision) {        case true: return "Yes, that's my decision";                        case false: return "No, that's my decision";      }   } } 

Produces the same error.

Even if you solved all the problems with enums being able to take on any value, you'd still have this issue. The flow analysis rules of the language simply do not consider switches without defaults to be "exhaustive" of all possible code paths, even when you and I know they are.

I would like very much to fix that, but frankly, we have many higher priorities than fixing this silly little issue, so we've never gotten around to it.

like image 152
Eric Lippert Avatar answered Sep 27 '22 16:09

Eric Lippert


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.

like image 34
Bryan Watts Avatar answered Sep 27 '22 17:09

Bryan Watts