I need to validate an integer to know if is a valid enum value.
What is the best way to do this in C#?
This is how I do it based on multiple posts online. The reason for doing this is to make sure enums marked with Flags
attribute can also be successfully validated.
public static TEnum ParseEnum<TEnum>(string valueString, string parameterName = null)
{
var parsed = (TEnum)Enum.Parse(typeof(TEnum), valueString, true);
decimal d;
if (!decimal.TryParse(parsed.ToString(), out d))
{
return parsed;
}
if (!string.IsNullOrEmpty(parameterName))
{
throw new ArgumentException(string.Format("Bad parameter value. Name: {0}, value: {1}", parameterName, valueString), parameterName);
}
else
{
throw new ArgumentException("Bad value. Value: " + valueString);
}
}
To validate if a value is a valid value in an enumeration, you only need to call the static method Enum.IsDefined.
int value = 99;//Your int value
if (Enum.IsDefined(typeof(your_enum_type), value))
{
//Todo when value is valid
}else{
//Todo when value is not valid
}
This answer is in response to deegee's answer which raises the performance issues of System.Enum so should not be taken as my preferred generic answer, more addressing enum validation in tight performance scenarios.
If you have a mission critical performance issue where slow but functional code is being run in a tight loop then I personally would look at moving that code out of the loop if possible instead of solving by reducing functionality. Constraining the code to only support contiguous enums could be a nightmare to find a bug if, for example, somebody in the future decides to deprecate some enum values. Simplistically you could just call Enum.GetValues once, right at the start to avoid triggering all the reflection, etc thousands of times. That should give you an immediate performance increase. If you need more performance and you know that a lot of your enums are contiguous (but you still want to support 'gappy' enums) you could go a stage further and do something like:
public abstract class EnumValidator<TEnum> where TEnum : struct, IConvertible
{
protected static bool IsContiguous
{
get
{
int[] enumVals = Enum.GetValues(typeof(TEnum)).Cast<int>().ToArray();
int lowest = enumVals.OrderBy(i => i).First();
int highest = enumVals.OrderByDescending(i => i).First();
return !Enumerable.Range(lowest, highest).Except(enumVals).Any();
}
}
public static EnumValidator<TEnum> Create()
{
if (!typeof(TEnum).IsEnum)
{
throw new ArgumentException("Please use an enum!");
}
return IsContiguous ? (EnumValidator<TEnum>)new ContiguousEnumValidator<TEnum>() : new JumbledEnumValidator<TEnum>();
}
public abstract bool IsValid(int value);
}
public class JumbledEnumValidator<TEnum> : EnumValidator<TEnum> where TEnum : struct, IConvertible
{
private readonly int[] _values;
public JumbledEnumValidator()
{
_values = Enum.GetValues(typeof (TEnum)).Cast<int>().ToArray();
}
public override bool IsValid(int value)
{
return _values.Contains(value);
}
}
public class ContiguousEnumValidator<TEnum> : EnumValidator<TEnum> where TEnum : struct, IConvertible
{
private readonly int _highest;
private readonly int _lowest;
public ContiguousEnumValidator()
{
List<int> enumVals = Enum.GetValues(typeof (TEnum)).Cast<int>().ToList();
_lowest = enumVals.OrderBy(i => i).First();
_highest = enumVals.OrderByDescending(i => i).First();
}
public override bool IsValid(int value)
{
return value >= _lowest && value <= _highest;
}
}
Where your loop becomes something like:
//Pre import-loop
EnumValidator< MyEnum > enumValidator = EnumValidator< MyEnum >.Create();
while(import) //Tight RT loop.
{
bool isValid = enumValidator.IsValid(theValue);
}
I'm sure the EnumValidator classes could written more efficiently (it’s just a quick hack to demonstrate) but quite frankly who cares what happens outside the import loop? The only bit that needs to be super-fast is within the loop. This was the reason for taking the abstract class route, to avoid an unnecessary if-enumContiguous-then-else in the loop (the factory Create essentially does this upfront). You will note a bit of hypocrisy, for brevity this code constrains functionality to int-enums. I should be making use of IConvertible rather than using int's directly but this answer is already wordy enough!
I found this link that answers it quite well. It uses:
(ENUMTYPE)Enum.ToObject(typeof(ENUMTYPE), INT)
You got to love these folk who assume that data not only always comes from a UI, but a UI within your control!
IsDefined
is fine for most scenarios, you could start with:
public static bool TryParseEnum<TEnum>(this int enumValue, out TEnum retVal)
{
retVal = default(TEnum);
bool success = Enum.IsDefined(typeof(TEnum), enumValue);
if (success)
{
retVal = (TEnum)Enum.ToObject(typeof(TEnum), enumValue);
}
return success;
}
(Obviously just drop the ‘this’ if you don’t think it’s a suitable int extension)