Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with user selecting value outside of Enum range

Tags:

c#

enums

I want the user to be able to type in a choice and have the program match their choice with one of the enum options. I have it set up in a loop so the user can keep trying if their entry doesn't match (i.e. Apple, Banana, Carrots).

enum Food {Apple, Banana, Carrot};

Food foodChoice;
while (!(Enum.TryParse<Food>(Console.ReadLine(), true, out foodChoice)))
{
    Console.WriteLine("Not a valid choice.");
}

This all works fine and dandy until the user enters, say 5. Obviously the Food enum doesn't have that many options and the TryParse will still output true, assigning foodChoice to 5. Is there a simple way to handle this?

like image 538
revival Avatar asked Dec 24 '22 12:12

revival


2 Answers

Try to use the Enum.IsDefined method:

Food foodChoice;
while (!Enum.TryParse(Console.ReadLine(), true, out foodChoice)
    || !Enum.IsDefined(typeof(Food), foodChoice))
{
    Console.WriteLine("Not a valid choice.");
}
like image 167
Dmitry Avatar answered Jan 11 '23 03:01

Dmitry


According to MSDN on this particular (and a little odd) behavior of TryParse:

Note that this value need not be a member of the TEnum enumeration. ... If value is the string representation of an integer that does not represent an underlying value of the TEnum enumeration, the method returns an enumeration member whose underlying value is value converted to an integral type. If this behavior is undesirable, call the IsDefined method to ensure that a particular string representation of an integer is actually a member of TEnum.

So all you need to do is check if the value actually exists by calling IsDefined in addition to parsing the string value:

!Enum.IsDefined(typeof(Food), foodChoice)

And now for the why? Integers are always treated as valid enum values. It doesn't check the actual value since it would require to calculate every possible combination of enum values. This is true since this is a valid enum value:

Food foodChoice = Food.Carrot|Food.Apple|Food.Banana;

In this case, there are just a few possible values, and a value of 5 is impossible. For longer enum the calculation can get enormous. That's why they omitted it in the parse step.

like image 32
Patrick Hofman Avatar answered Jan 11 '23 05:01

Patrick Hofman