views:

185

answers:

3

HI, I've got a simple question, but one that has been bugging me for a while.

Question:

When using switch statements in C#, is it considered better practice to use enums over constants or vice versa? Or is it a matter of preference? I ask this because many people seem to like using enums, but when you are switching on an int value, you have to cast each of the values contained in the enum to an int, even if you specify the type of enum.

Code Snippet:

class Program
{

     enum UserChoices
     {
        MenuChoiceOne = 1,
        MenuChoiceTwo,
        MenuChoiceThree,
        MenuChoiceFour,
        MenuChoiceFive
     }

     static void Main()
     {

        Console.Write("Enter your choice: ");
        int someNum = int.Parse(Console.ReadLine());

        switch (someNum)
        {
            case (int)UserChoices.MenuChoiceOne:
              Console.WriteLine("You picked the first choice!");
              break;
            // etc. etc.
         }
      }
}

Is there some way you can create an instance of the enum and just cast the whole enum to an int?

Thanks!

+10  A: 

Why not do this instead?

UserChoices choice = (UserChoices)int.Parse(Console.ReadLine());

switch (choice)
{
    case UserChoices.MenuChoiceOne:
        // etc...

Then you only need to cast once.

Update: fixed bug in code!

Mark Byers
thanks! I understand it now.
Alex
This would be my approach as well. However, one thing to consider is where your int value is coming from. In this case, you're reading user input from the console, so it's possible that the user will type in a value that doesn't correspond to any values in the UserChoices enum. In that case I believe a cast will throw an exception, which may or may not be the behavior that you want. If you are not sure if the value you have is a valid enum value, you can use the Enum.IsDefined function to find out.
Dr. Wily's Apprentice
No, if you cast an int to a value that doesn't exist, no exception is thrown (try it). You should use a "default:" case to handle this situation. The int.Parse can throw though, but that was in the original code - I didn't change that.
Mark Byers
Yes, my mistake; no exception is thrown on this cast. I should have tried it first. I was probably thinking about using the Enum.Parse method to convert strings into enum values, which will throw an exception if the string passed does not match the name of one of the enum values.
Dr. Wily's Apprentice
+1  A: 

I believe you can simply do:

switch((UserChoices)someNum)
{
     case UserChoices.MenuChoiceOne:
     break;
     default:
     throw Exception // whatever here
}
Crowe T. Robot
+2  A: 

I think the preference of enums over constants is because of readability and not because of performance. I find it easier to read enums in code (in general and not just in switch statements), than to read/understand constants and their usage.

and btw, you don't have to cast every case, you can just cast your switch.

switch((UserChoices)someEnum)
{
...
Joseph
ok, it works, but what exactly is happening when you do that? are you casting the int someEnum to a type of your enum?
Alex