7

There are a few other Questions on how to convert Enums and what happens if the value parsed is out-of-range, like in:

public enum SomeTypes
{
    SomeType1 = 1,
    SomeType2 = 2,
    SomeType3 = 3
}

public class SomeClass
{
    ...
    var inRange = (SomeTypes) 1;
    var outOfRange = (SomeTypes) 5;
    ...
}

Going out-of-range will not produce any error. But I found the hard way that if you try to serialize-deserialize an enum with an out-of-range value you'll get weird errors. For example, I was getting something like

"error parsing the message or timeout exceeded"

which kept me looking for other reasons than the enum out-of-range.

Suggestions to handle this are by the means of the Enum.IsDefined. That seems to work quite nicely, but then there's this rather bold warning on msdn:

"Do not use System.Enum.IsDefined(System.Type,System.Object) for enumeration range checks as it is based on the runtime type of the enumeration, which can change from version to version."

So, my question is, can we safely use Enum.IsDefined or what is the correct way to check if the value of an enum is out-of-range without using the Enum.IsDefined?

nando
  • 89
  • 1
  • 1
  • 6
  • Use `Enum.GetValues`, find min and max of it. Then you can easily check whether the value is in range or not. If course, this idea won't work for Bit flags. – Sriram Sakthivel Nov 21 '14 at 11:18
  • 1
    Add a `Parse()` or a `TryParse()` method and use that instead of simply casting. – BCdotWEB Nov 21 '14 at 11:22
  • 5
    That warning is based on the assumption that the enum declaration is not in the same place as the validation code. In other words, a later revision of the code might add additional enum members but the code that uses the enum wasn't updated to deal with that. Could happen, but very unlikely to apply to your case. The bigger problem is that when you avoid IsDefined then you'll have a new bug in your code. So ignore this advice. – Hans Passant Nov 21 '14 at 14:19
  • @BCdotNET dont think that changes anything, as the documentation goes: _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._ – nando Nov 21 '14 at 14:23
  • 1
    @HansPassant Thanks, if that's the only problem, then I can live with it. Using the IsDefined seems to be cleaner than the other suggestions given so far... – nando Nov 21 '14 at 14:31

3 Answers3

5

Use Enum.GetValues():

public bool IsInRange(int value){
  var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x);

  return value >= values.First() && value <= values.Last();
}

[EDIT]

In case you want to check if the item is defined instead of just checking if it's inside the range, you can do similarly:

public bool IsDefined(int value){
  var values = Enum.GetValues(typeof(SomeTypes)).Cast<int>().OrderBy(x => x);

  return values.Contains(value);
}
Joanvo
  • 5,677
  • 2
  • 25
  • 35
  • 2
    This would probably work, but it adds a hidden limitation that I wonder if it will be obvious if in the future someone adds non-sequential enum values... – nando Nov 21 '14 at 14:33
5

There is an option for something simpler:

int value;
bool isInRange = !string.IsNullOrEmpty(Enum.GetName(typeof(myEnumType), value));
DirectionUnkown
  • 203
  • 3
  • 9
0

I did a similar thing with objects DataContract You must decorate the items in the list with [EnumMember] and then you could obtain the enum name with this method. So you would know if value exists in the enum cos returns his enum name.

public static string GetEnumNameFromValue(System.Type typeEnum, string value)
        {
            FieldInfo[] fis = typeEnum.GetFields();
            foreach (FieldInfo fi in fis)
            {
                EnumMemberAttribute[] attributes = (EnumMemberAttribute[])fi.GetCustomAttributes(typeof(EnumMemberAttribute), false);
                if (attributes.Length > 0)
                {
                    if (string.Compare(attributes[0].Value, value, true) == 0)
                    {
                        return fi.Name;
                    }
                }
            }
            return null;
        }
mggSoft
  • 992
  • 2
  • 20
  • 35