97

I need to validate an integer to know if is a valid enum value.

What is the best way to do this in C#?

Deanna
  • 23,876
  • 7
  • 71
  • 156
Jedi Master Spooky
  • 5,629
  • 13
  • 57
  • 86
  • 1
    For an approach with flags it might be useful to checkout this answer on a duplicate question: http://stackoverflow.com/a/23177585/5190842 – Erik Oct 07 '15 at 18:40
  • Check `EnumDataTypeAttribute` – Timeless Jul 14 '17 at 07:15
  • fastest way is to not validate enum and use default behavior, any enum should have member like "None" or "Default" or something like that. you could use switch default case. – M.kazem Akhgary Mar 04 '19 at 04:53
  • The top-voted answers came before a high-performance `IsDefined` was added to .Net 5. See [Timo's answer](https://stackoverflow.com/a/55028274/199364). 11 years later, so missing 11 years of upvotes. – ToolmakerSteve Aug 04 '23 at 21:37

13 Answers13

106

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)

Aage
  • 5,932
  • 2
  • 32
  • 57
Vman
  • 3,016
  • 2
  • 24
  • 20
  • 16
    Please also note that Enum.IsDefined uses reflection which could cause performance problems – Guldan May 04 '15 at 13:11
  • 2
    Having already checked `IsDefined()` why not just cast the int in the success condition: `retVal = (TEnum)enumValue` ? – Matt Jenkins Jun 27 '19 at 18:14
  • 1
    @jeromej I was asking why can't we use `retVal = (TEnum)enumvalue` instead of `retVal = (TEnum)Enum.ToObject(typeof(TEnum), enumValue)` in the success condition. We've already confirmed that `enumValue` `IsDefined()`. – Matt Jenkins Oct 07 '20 at 09:41
  • @MattJenkins Right. I can't read, my bad. Deleting my comment now. – jeromej Oct 07 '20 at 11:09
  • It is explicitly stated in docs not to use Enum.IsDefined for range checks: "DO NOT use Enum.IsDefined for enum range checks." Better refer to other answers that use other methods. https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/parameter-design – Guney Ozsan Jun 25 '21 at 14:50
  • 1
    @GuneyOzsan True, but this isn't a range check. If you are 100% sure you have contiguous enums and a simple max-check will do then go for something like a programmatically defined const (and hope people remember to keep it up to date) or a "last value" type approach ie: enum MyEnum{val1,val2,val3,LAST_VAL=val3}. Both have their downsides (mainly "a bit naff" for a this century language) but as discussed, both are faster. – Vman Jun 29 '21 at 13:24
28

IMHO the post marked as the answer is incorrect.
Parameter and data validation is one of the things that was drilled into me decades ago.

WHY

Validation is required because essentially any integer value can be assigned to an enum without throwing an error.
I spent many days researching C# enum validation because it is a necessary function in many cases.

WHERE

The main purpose in enum validation for me is in validating data read from a file: you never know if the file has been corrupted, or was modified externally, or was hacked on purpose.
And with enum validation of application data pasted from the clipboard: you never know if the user has edited the clipboard contents.

That said, I spent days researching and testing many methods including profiling the performance of every method I could find or design.

Making calls into anything in System.Enum is so slow that it was a noticeable performance penalty on functions that contained hundreds or thousands of objects that had one or more enums in their properties that had to be validated for bounds.

Bottom line, stay away from everything in the System.Enum class when validating enum values, it is dreadfully slow.

RESULT

The method that I currently use for enum validation will probably draw rolling eyes from many programmers here, but it is imho the least evil for my specific application design.

I define one or two constants that are the upper and (optionally) lower bounds of the enum, and use them in a pair of if() statements for validation.
One downside is that you must be sure to update the constants if you change the enum.
This method also only works if the enum is an "auto" style where each enum element is an incremental integer value such as 0,1,2,3,4,.... It won't work properly with Flags or enums that have values that are not incremental.

Also note that this method is almost as fast as regular if "<" ">" on regular int32s (which scored 38,000 ticks on my tests).

For example:

public const MyEnum MYENUM_MINIMUM = MyEnum.One;
public const MyEnum MYENUM_MAXIMUM = MyEnum.Four;

public enum MyEnum
{
    One,
    Two,
    Three,
    Four
};

public static MyEnum Validate(MyEnum value)
{
    if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
    if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
    return value;
}

PERFORMANCE

For those who are interested, I profiled the following variations on an enum validation, and here are the results.

The profiling was performed on release compile in a loop of one million times on each method with a random integer input value. Each test was ran more than 10 times and averaged. The tick results include the total time to execute which will include the random number generation etc. but those will be constant across the tests. 1 tick = 10ns.

Note that the code here isn't the complete test code, it is only the basic enum validation method. There were also a lot of additional variations on these that were tested, and all of them with results similar to those shown here that benched 1,800,000 ticks.

Listed slowest to fastest with rounded results, hopefully no typos.

Bounds determined in Method = 13,600,000 ticks

public static T Clamp<T>(T value)
{
    int minimum = Enum.GetValues(typeof(T)).GetLowerBound(0);
    int maximum = Enum.GetValues(typeof(T)).GetUpperBound(0);

    if (Convert.ToInt32(value) < minimum) { return (T)Enum.ToObject(typeof(T), minimum); }
    if (Convert.ToInt32(value) > maximum) { return (T)Enum.ToObject(typeof(T), maximum); }
    return value;
}

Enum.IsDefined = 1,800,000 ticks
Note: this code version doesn't clamp to Min/Max but returns Default if out of bounds.

public static T ValidateItem<T>(T eEnumItem)
{
    if (Enum.IsDefined(typeof(T), eEnumItem) == true)
        return eEnumItem;
    else
        return default(T);
}

System.Enum Convert Int32 with casts = 1,800,000 ticks

public static Enum Clamp(this Enum value, Enum minimum, Enum maximum)
{
    if (Convert.ToInt32(value) < Convert.ToInt32(minimum)) { return minimum; }
    if (Convert.ToInt32(value) > Convert.ToInt32(maximum)) { return maximum; }
    return value;
}

if() Min/Max Constants = 43,000 ticks = the winner by 42x and 316x faster.

public static MyEnum Clamp(MyEnum value)
{
    if (value < MYENUM_MINIMUM) { return MYENUM_MINIMUM; }
    if (value > MYENUM_MAXIMUM) { return MYENUM_MAXIMUM; }
    return value;
}

-eol-

deegee
  • 1,553
  • 14
  • 13
  • 12
    A large number of our enums are not contiguous so not an option in many scenarios. 'Enum.IsDefined(typeof(T)' will be slow in your test scenario as .net is doing lots of reflection, boxing, etc. Calling this every time you parse a line in your import file is never going to be fast. If performance is key then I would look at calling Enum.GetValues once at the start of the import. It will never be as fast a simple <> compare but you know it will work for all enums. Alternatively you could have a more intelligent enum parser, I’ll post another answer as there isn't the space to respond neatly! – Vman Feb 24 '14 at 13:26
  • 2
    @johnny 5 - From the information above: This method also only works if the enum is an "auto" style where each enum element is an incremental integer value such as 0,1,2,3,4,.... It won't work properly with Flags or enums that have values that are not incremental. – deegee Jun 11 '15 at 16:57
  • @Vman - "Calling this every time you parse a line in your import file is never going to be fast." - It will be significantly faster than the drive's read speed. – deegee Jun 11 '15 at 17:00
  • Perhaps some other process might want a piece of that hard drive action? Death by a thousand cuts. – Vman Jun 12 '15 at 00:22
  • Premature optimization. The vast majority of cases will not be processing sufficient numbers of enums from files to have any significant impact on performance. Test it, and if there are performance issues, then test and choose the best method to deal with it. – deegee Jun 12 '15 at 02:35
  • @deegee: You're jumping to an unsupported assumption. Disk cache is much faster than reflection. Modern SSDs are faster than reflection. Spinning disks with low fragmentation might be faster than reflection. I can well believe that file-reading performance is slower than reflection, but only because I've seen so much file access code that can't keep up with the disk. – Ben Voigt Oct 27 '16 at 07:29
  • as @johnny said, what if we have: `enum ColorDepth { Monochrome = 1, Grayscale = 7, EightBit = 8, SixteenBit = 16, TrueColor = 24, DeepColor = 48 }` in which `2` is less than (int)ColorDepth.DeepColor but still is an invalid value. – Tohid Apr 03 '20 at 06:21
  • Combine the two approaches: Do the bounds check, to very quickly reject values out of range. If in range, and enum has discontiguous values, then use `IsDefined` to reject those interior holes. If there are a small number of missing values, could write a custom method that explicitly checks for those (if the range check succeeds). – ToolmakerSteve Aug 04 '23 at 21:31
19

Update 2022-09-27

As of .NET 5, a fast, generic overload is available: Enum.IsDefined<TEnum>(TEnum value).

The generic overload alleviates the performance issues of the non-generic one.

Original Answer

Here is a fast generic solution, using a statically-constucted HashSet<T>.

You can define this once in your toolbox, and then use it for all your enum validation.

public static class EnumHelpers
{
    /// <summary>
    /// Returns whether the given enum value is a defined value for its type.
    /// Throws if the type parameter is not an enum type.
    /// </summary>
    public static bool IsDefined<T>(T enumValue)
    {
        if (typeof(T).BaseType != typeof(System.Enum)) throw new ArgumentException($"{nameof(T)} must be an enum type.");

        return EnumValueCache<T>.DefinedValues.Contains(enumValue);
    }

    /// <summary>
    /// Statically caches each defined value for each enum type for which this class is accessed.
    /// Uses the fact that static things exist separately for each distinct type parameter.
    /// </summary>
    internal static class EnumValueCache<T>
    {
        public static HashSet<T> DefinedValues { get; }

        static EnumValueCache()
        {
            if (typeof(T).BaseType != typeof(System.Enum)) throw new Exception($"{nameof(T)} must be an enum type.");

            DefinedValues = new HashSet<T>((T[])System.Enum.GetValues(typeof(T)));
        }
    }
}

Note that this approach is easily extended to enum parsing as well, by using a dictionary with string keys (minding case-insensitivity and numeric string representations).

Timo
  • 7,992
  • 4
  • 49
  • 67
17

As others have mentioned, Enum.IsDefined is slow, something you have to be aware of if it's in a loop.

When doing multiple comparisons, a speedier method is to first put the values into a HashSet. Then simply use Contains to check whether the value is valid, like so:

int userInput = 4;
// below, Enum.GetValues converts enum to array. We then convert the array to hashset.
HashSet<int> validVals = new HashSet<int>((int[])Enum.GetValues(typeof(MyEnum)));
// the following could be in a loop, or do multiple comparisons, etc.
if (validVals.Contains(userInput))
{
    // is valid
}
Doug S
  • 10,146
  • 3
  • 40
  • 45
  • Another take on this answer would be to have a `HashSet` which would remove the need to cast to `int` if you are validating an `enum` instead of an `int`. Code to set it up would look like: `var validVals = new HashSet(Enum.GetValues(typeof(MyEnum)).Cast());`. Usage would be the same of course. – Erik Oct 07 '15 at 18:48
  • 1
    It just so happens that HashSet is much faster than HashSet for some reason, so casting to int before doing the check speeds things up drastically. – Dwedit Apr 12 '19 at 14:30
  • 1
    But be aware of the additionall allocations by `GetValues` and `new HashSet`. In hot paths this will reduce the throughput. – Andre Kampling Jul 12 '21 at 09:30
9

Brad Abrams specifically warns against Enum.IsDefined in his post The Danger of Oversimplification.

The best way to get rid of this requirement (that is, the need to validate enums) is to remove ways where users can get it wrong, e.g., an input box of some sort. Use enums with drop downs, for example, to enforce only valid enums.

0xced
  • 25,219
  • 10
  • 103
  • 255
Jon Limjap
  • 94,284
  • 15
  • 101
  • 152
  • 7
    My input comes from an XML file produced by one of many possible programs that I don't control where the quality of data varies greatly. Is Enum.IsDefined really that bad because it seems best for me in this situation? – Richard Garside Jul 30 '11 at 14:58
  • @Richard As with anything in life, there are specific cases wherein what is generally a bad idea will be the appropriate solution for that situation. If you feel that that is the best solution for your case, go ahead. :) Even singletons and global variables and nested ifs are a good idea for certain situations... – Jon Limjap Aug 01 '11 at 06:31
  • 8
    Your approach (limiting what's available in the UI) has the same drawbacks as `Enum.IsDefined`: If the UI code is out of sync with the enum, then you can get out-of-range values (i.e. not declared in the enum). Although one still needs to handle these values (like having a `default` case in `switch` statements), it seems a good practice to use `Enum.IsDefined` before storing a value in an object's field: it allows the error to be caught early, instead of letting it float around until it is not clear anymore where the bogus value came from. – Suzanne Soy Mar 14 '13 at 16:12
  • 31
    The recommendation for only putting enums into drop-down boxes works fine for WinForms, but fails for WebForms, where you need to validate against malicious input. – Brad Wilson Aug 17 '08 at 16:04
  • Which is why you always define a default case in your switch statements. – Trisped Oct 12 '12 at 20:24
7

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!

Vman
  • 3,016
  • 2
  • 24
  • 20
5

Building upon Timo's answer, here is an even faster, safer and simpler solution, provided as an extension method.

public static class EnumExtensions
{
    /// <summary>Whether the given value is defined on its enum type.</summary>
    public static bool IsDefined<T>(this T enumValue) where T : Enum
    {
        return EnumValueCache<T>.DefinedValues.Contains(enumValue);
    }
    
    private static class EnumValueCache<T> where T : Enum
    {
        public static readonly HashSet<T> DefinedValues = new HashSet<T>((T[])Enum.GetValues(typeof(T)));
    }
}

Usage:

if (myEnumValue.IsDefined()) { ... }

Update - it's even now cleaner in .NET 5:

public static class EnumExtensions
{
    /// <summary>Whether the given value is defined on its enum type.</summary>
    public static bool IsDefined<T>(this T enumValue) where T : struct, Enum
    {
        return EnumValueCache<T>.DefinedValues.Contains(enumValue);
    }

    private static class EnumValueCache<T> where T : struct, Enum
    {
        public static readonly HashSet<T> DefinedValues = new(Enum.GetValues<T>());
    }
}
Matt Jenkins
  • 2,824
  • 1
  • 30
  • 34
1

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);
    }
}
Schultz9999
  • 8,717
  • 8
  • 48
  • 87
1

You can use the FluentValidation for your project. Here is a simple example for the "Enum Validation"

Let's create a EnumValidator class with using FluentValidation;

public class EnumValidator<TEnum> : AbstractValidator<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable
{
    public EnumValidator(string message)
    {
        RuleFor(a => a).Must(a => typeof(TEnum).IsEnum).IsInEnum().WithMessage(message);
    }

}

Now we created the our enumvalidator class; let's create the a class to call enumvalidor class;

 public class Customer 
{
  public string Name { get; set; }
  public Address address{ get; set; }
  public AddressType type {get; set;}
}
public class Address 
{
  public string Line1 { get; set; }
  public string Line2 { get; set; }
  public string Town { get; set; }
  public string County { get; set; }
  public string Postcode { get; set; }

}

public enum AddressType
{
   HOME,
   WORK
}

Its time to call our enum validor for the address type in customer class.

public class CustomerValidator : AbstractValidator<Customer>
{
    public CustomerValidator()
   {
     RuleFor(x => x.type).SetValidator(new EnumValidator<AddressType>("errormessage");
  }
}
Cemal
  • 153
  • 2
  • 8
1

To expound on the performance scaling specifically regarding Timo/Matt Jenkins method: Consider the following code:

//System.Diagnostics - Stopwatch
//System - ConsoleColor
//System.Linq - Enumerable
Stopwatch myTimer = Stopwatch.StartNew();
int myCyclesMin = 0;
int myCyclesCount = 10000000;
long myExt_IsDefinedTicks;
long myEnum_IsDefinedTicks;
foreach (int lCycles in Enumerable.Range(myCyclesMin, myCyclesMax))
{
    Console.WriteLine(string.Format("Cycles: {0}", lCycles));

    myTimer.Restart();
    foreach (int _ in Enumerable.Range(0, lCycles)) { ConsoleColor.Green.IsDefined(); }
    myExt_IsDefinedTicks = myTimer.ElapsedTicks;

    myTimer.Restart();
    foreach (int _ in Enumerable.Range(0, lCycles)) { Enum.IsDefined(typeof(ConsoleColor), ConsoleColor.Green); }
    myEnum_IsDefinedTicks = myTimer.E

    Console.WriteLine(string.Format("object.IsDefined() Extension Elapsed: {0}", myExt_IsDefinedTicks.ToString()));
    Console.WriteLine(string.Format("Enum.IsDefined(Type, object): {0}", myEnum_IsDefinedTicks.ToString()));
    if (myExt_IsDefinedTicks == myEnum_IsDefinedTicks) { Console.WriteLine("Same"); }
    else if (myExt_IsDefinedTicks < myEnum_IsDefinedTicks) { Console.WriteLine("Extension"); }
    else if (myExt_IsDefinedTicks > myEnum_IsDefinedTicks) { Console.WriteLine("Enum"); }
}

Output starts out like the following:

Cycles: 0
object.IsDefined() Extension Elapsed: 399
Enum.IsDefined(Type, object): 31
Enum
Cycles: 1
object.IsDefined() Extension Elapsed: 213654
Enum.IsDefined(Type, object): 1077
Enum
Cycles: 2
object.IsDefined() Extension Elapsed: 108
Enum.IsDefined(Type, object): 112
Extension
Cycles: 3
object.IsDefined() Extension Elapsed: 9
Enum.IsDefined(Type, object): 30
Extension
Cycles: 4
object.IsDefined() Extension Elapsed: 9
Enum.IsDefined(Type, object): 35
Extension

This seems to indicate there is a steep setup cost for the static hashset object (in my environment, approximately 15-20ms. Reversing which method is called first doesn't change that the first call to the extension method (to set up the static hashset) is quite lengthy. Enum.IsDefined(typeof(T), object) is also longer than normal for the first cycle, but, interestingly, much less so.

Based on this, it appears Enum.IsDefined(typeof(T), object) is actually faster until lCycles = 50000 or so.

I'm unsure why Enum.IsDefined(typeof(T), object) gets faster at both 2 and 3 lookups before it starts rising. Clearly there's some process going on internally as object.IsDefined() also takes markedly longer for the first 2 lookups before settling in to be bleeding fast.

Another way to phrase this is that if you need to lots of lookups with any other remotely long activity (perhaps a file operation like an open) that will add a few milliseconds, the initial setup for object.IsDefined() will be swallowed up (especially if async) and become mostly unnoticeable. At that point, Enum.IsDefined(typeof(T), object) takes roughly 5x longer to execute.

Basically, if you don't have literally thousands of calls to make for the same Enum, I'm not sure how hashing the contents is going to save you time over your program execution. Enum.IsDefined(typeof(T), object) may have conceptual performance problems, but ultimately, it's fast enough until you need it thousands of times for the same enum.

As an interesting side note, implementing the ValueCache as a hybrid dictionary yields a startup time that reaches parity with Enum.IsDefined(typeof(T), object) within ~1500 iterations. Of course, using a HashSet passes both at ~50k.

So, my advice: If your entire program is validating the same enum (validating different enums causes the same level of startup delay, once for each different enum) less than 1500 times, use Enum.IsDefined(typeof(T), object). If you're between 1500 and 50k, use a HybridDictionary for your hashset, the initial cache populate is roughly 10x faster. Anything over 50k iterations, HashSet is a pretty clear winner.

Also keep in mind that we are talking in Ticks. In .Net a 10,000 ticks is 1 ms.

For full disclosure I also tested List as a cache, and it's about 1/3 the populate time as hashset, however, for any enum over 9 or so elements, it's way slower than any other method. If all your enums are less than 9 elements, (or smaller yet) it may be the fastest approach.

The cache defined as a HybridDictionary (yes, the keys and values are the same. Yes, it's quite a bit harder to read than the simpler answers referenced above):

//System.Collections.Specialized - HybridDictionary
private static class EnumHybridDictionaryValueCache<T> where T : Enum
        {
            static T[] enumValues = (T[])Enum.GetValues(typeof(T));

            static HybridDictionary PopulateDefinedValues()
            {
                HybridDictionary myDictionary = new HybridDictionary(enumValues.Length);
                foreach (T lEnumValue in enumValues)
                {
                    //Has to be unique, values are actually based on the int value. Enums with multiple aliases for one value will fail without checking.
                    //Check implicitly by using assignment.
                    myDictionary[lEnumValue] = lEnumValue;
                }
                return myDictionary;
            }

            public static readonly HybridDictionary DefinedValues = PopulateDefinedValues();
        }

0

I found this link that answers it quite well. It uses:

(ENUMTYPE)Enum.ToObject(typeof(ENUMTYPE), INT)
shA.t
  • 16,580
  • 5
  • 54
  • 111
Mike Polen
  • 3,586
  • 1
  • 27
  • 31
  • Won't this just throw an exception if a non-enum integer is passed to it? – Richard Garside Jul 30 '11 at 15:02
  • 3
    @Richard - yes it will...been 3 years since I wrote this and heaven help me if I know what I was thinking other than - if it throws it isn't – Mike Polen Aug 04 '11 at 17:57
  • Throwing an Exception has performance losses as well. You should never throw an Exception when there is a better solution. – Kody Dec 30 '15 at 19:01
0

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
}
Juan Carlos Velez
  • 2,840
  • 2
  • 34
  • 48
  • 4
    Downvoted not for being wrong, but for writing an answer 8 years late that provides no new information that isn't already in the accepted answer. – Ben Voigt Oct 27 '16 at 07:32
0

Several answers discuss performance concerns of using Enum.IsDefined so I decided to test it with the latest .NET 7 (using BenchmarkDotNet).

Conclusion: Explicit comparison (range check or using ==) is faster, but Enum.IsDefined should be fast enough for most almost all real world use cases:

Method Mean Error StdDev Allocated
IsDefined 10.2906 ns 0.2260 ns 0.2321 ns -
EqualCheck 0.4802 ns 0.0148 ns 0.0139 ns -
RangeCheck 0.0221 ns 0.0131 ns 0.0123 ns -

For reference, this is the test code:

public enum MySequentialEnum { First, Second, Third, Fourth }

private MySequentialEnum SequentialEnumExisting = MySequentialEnum.Second;

[Benchmark]
public bool IsDefined()
{
    return Enum.IsDefined(SequentialEnumExisting);
}

[Benchmark]
public bool EqualCheck()
{
    return SequentialEnumExisting is MySequentialEnum.First or MySequentialEnum.Second or MySequentialEnum.Third or MySequentialEnum.Fourth;
}

[Benchmark]
public bool RangeCheck()
{
    return SequentialEnumExisting is >= MySequentialEnum.First and <= MySequentialEnum.Fourth;
}

Note: I did some additional benchmarks with non existing enum values, and enums with [Maps] attribute but did not find any relevant differences to the standard sequential enum

Isak Savo
  • 34,957
  • 11
  • 60
  • 92