32

I want to check that some integer type belongs to (an) enumeration member.

For Example,

public enum Enum1
{
    member1 = 4,

    member2 = 5,

    member3 = 9,

    member4 = 0
}

Enum1 e1 = (Enum1)4 gives me member1

Enum1 e2 = (Enum1)10 gives me nothing and I want to check it.

Alexander Stalt
  • 977
  • 5
  • 15
  • 22

9 Answers9

69

Use Enum.IsDefined

Enum.IsDefined(typeof(Enum1), 4) == true

but

Enum.IsDefined(typeof(Enum1), 1) == false
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182
  • 8
    Don't use this if you require speed: Enum.IsDefined uses Reflection and is **very** slow. – ereOn Apr 09 '10 at 06:17
  • 11
    First, micro-optimization is a waste of programming effort. Second, `Enum.IsDefined` will run over 2,000 times per millisecond. I wouldn't consider that slow. – Samuel Neff Apr 09 '10 at 06:33
  • ereOn, How can I make it faster ? – Alexander Stalt Apr 09 '10 at 06:34
  • 2
    @Sam: I precised *"if you require speed"*. If you do this in, for example, a network frame treatment loop, you might get terrible results in the end. @Alexander Stalt: Unless you check each value one by one, you can't I suppose. But that's overkill (in terms of code length). The real question is: is such a test really needed ? Usually, a switch statement handling all the possible values and a *"default"* one is enough. But we obviously lack of information to discuss that here (and it's probably off-topic) – ereOn Apr 09 '10 at 06:55
  • @ereOn, I have an xml file. I store my program settings there. Some settings are enumeration types, so i save (int)Enum1.member1. When I load that file, I must to check if some settings correct because someone else could change them. – Alexander Stalt Apr 09 '10 at 07:08
  • If you only load (and parse) that XML file once (or not very often), you can just use Sam's solution: even if Enum.IsDefined is slow, it is probably still way faster than the I/O operation on your XML file, so not really a problem here imho. – ereOn Apr 09 '10 at 07:20
  • Is speed is a problem, simply cache the results. – James Westgate Apr 09 '10 at 07:44
  • @ereOn, If speed is so much of a concern that `Enum.IsDefined` is too slow for a particular application, then .NET is not the right choice in the first place. – Samuel Neff Apr 09 '10 at 13:45
  • 1
    So it is ok to write badly-designed/unoptimized code because C# is *slow* anyway ? I tend to agree on the fact that micro-optimization often doesn't pay as much as it costs. But avoiding reflection when it is not **really** needed is **not** a waste of programming effort. 2000 times/ms (on *your* computer for which we don't know the specifications) is *slow* for something as simple as a 32/64 bits matching process. I however admit that in this very case (and in most cases), it doesn't really matter. – ereOn Apr 09 '10 at 14:49
  • @ereOn, `Enum.IsDefined` **is not slow**. You'd be better off outlawing `String.Format` since [on my laptop] it can only be run 931 times per millisecond which is nothing compared to `Enum.IsDefined`'s 2000+ calls. – Samuel Neff Apr 09 '10 at 15:34
  • @ere, there are times when micro-optimization is important. In our own application we had to replace all `String.Format` calls within the context of our reports and use `String.Concat` instead. We only did this in the one place that the profiler showed it was needed and it made a noticeable difference over the several hundred thousand iterations done for each report. However, this experience wouldn't drive me to tell other people to avoid `String.Format` all the time. – Samuel Neff Apr 09 '10 at 15:35
  • 1
    You're obviously missing the point. Maybe you should compare performances between `Enum.IsDefined` and another method that doesn't use reflection. Your performances results are pointless, since we don't know your computer specifications and have **nothing** to compare them with. Anyway, my first comment stated **"if you require speed"** which is an important **if**. So again, avoid using this method if speed is an important requirement. `Enum.IsDefined` **is** slow regarding what it does and how he does it ;) – ereOn Apr 10 '10 at 11:56
  • 1
    @ereOn, I would say the exact same thing, you're missing the point. This whole thing blanket **if you require speed** is ridiculous. You scared the OP into not using `Enum.IsDefined` when it's probably the most appropriate option for his situation. The question is if a particular statement is used in a way that would degrade performance in a meaningful way. Comparing `Enum.IsDefined` to *32/64 bit matching process* is completely irrelevant since you first need to get all the values to compare against which would require hard coding them again in a `switch` or using `Enum.GetValues`. – Samuel Neff Apr 10 '10 at 13:07
  • 9
    I'm sorry if I somehow offended you by warning the OP about the possible slowness of your method **in some particular situations**. I agree with your answer ! However, efficient coding *sometimes* require to write a few lines: not everything can be done in one call ;) If the OP doesn't require very high performance and prefers code simplicity, then your solution is **just perfect**. And that's what I said in my third comment. I often use `Enum.IsDefined` method myself, but I wouldn't in some particular cases. Anyway, the OP accepted your answer (and I even upvoted it) so... ;) – ereOn Apr 10 '10 at 14:10
5

As Sam says, you can use IsDefined. This is somewhat awkward though. You may want to look at my Unconstrained Melody library which would let you us:

Enum1 e2 = (Enum1)10;
if (e2.IsNamedValue()) // Will return false
{
}

It's probably not worth it for a single enum call, but if you're doing a lot of stuff with enums you may find some useful things in there.

It should be quicker than Enum.IsDefined btw. It only does a linear scan at the moment, but let me know if you need that to be improved :) (Most enums are small enough that they probably wouldn't benefit from a HashSet, but we could do a binary search...)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3
int testNum = 5;
bool isMember = Enum.GetValues(typeof(Enum1)).Cast<int>().Any(x => x == testNum);
Cornelius
  • 3,526
  • 7
  • 37
  • 49
1

You look through the values of the enum and compare them to the integer.

    static bool EnumTest(int testVal, Enum e)
    {
        bool result = false;
        foreach (var val in Enum.GetValues(typeof(Enum1)))
        {
            if ((int)val == testVal)
            {
                result = true;
                break;
            }
        }
        return result;
    }

Edit: Looks like Sam has a better solution.

Community
  • 1
  • 1
Jim McKeeth
  • 38,225
  • 23
  • 120
  • 194
1

You can use Enum.GetValues to get all defined values. Then check if your value exists in that list.
http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx

Hans Kesting
  • 38,117
  • 9
  • 79
  • 111
0

Be careful this won't work if you have an enum for 3 (Apples and Pears) the methods above won't detect it as valid.

[Flags]
public enum Fruit
{ 

    Apples=1,

    Pears=2,

    Oranges =4,

}
David Homer
  • 396
  • 2
  • 8
0

Here's a succinct little snippet from an extension method I wrote a few years ago. Combines TryParse with IsDefined to do it all in one swoop and handle values that don't exist in the enum.

if (value != null)
{
    TEnum result;
    if (Enum.TryParse(value.ToString(), true, out result))
    {
        // since an out-of-range int can be cast to TEnum, double-check that result is valid
        if (Enum.IsDefined(typeof(TEnum), result.ToString() ?? string.Empty))
        {
            return result;
        }
    }
}

Here's the extension for integer values

public static TEnum ParseToEnum<TEnum>(this int value, TEnum? defaultValue = null, bool useEnumDefault = false) where TEnum : struct
{
    return ParseToEnumInternal(value, defaultValue, useEnumDefault);
}

And a usage

public enum Test
{
    Value1 = 1,
    Value2 = 3
}
    
var intValue = 1;
var enumParsed = intValue.ParseToEnum<Test>(); // converts to Test.Value1
intValue = 2;
enumParsed = intValue.ParseToEnum<Test>(); // either throws or converts to supplied default
enumParsed = 3.ParseToEnum<Test>(); // converts to Test.Value2

Some people don't like how it dangles off the end of the (potentially nullable) value, but I have an extension that handles null values of nullable types (int?) and I like it myself, so ...

I can post like a Gist of the whole extension method with all the overloads if you're interested.

sliderhouserules
  • 3,415
  • 24
  • 32
0

Use:

if (Enum.IsDefined(typeof(Fruit),e2))
{
   //Valid Value
}
else
{
   //Invalid ENum Value
}
John Foll
  • 121
  • 1
  • 10
  • 1
    How does this add to the [accepted answer](https://stackoverflow.com/a/2605417/3744182) of [Samuel Neff](https://stackoverflow.com/users/118703/samuel-neff) which suggests, *Use `Enum.IsDefined`: `Enum.IsDefined(typeof(Enum1), 4) == true`* ? – dbc Apr 03 '21 at 18:04
  • I am showing a different way to answer the question of this original post: "Check that integer type belongs to enum member". I didn't see anyone who posted this response to the question. I think that this is the cleanest way and is also accurate to know if an integer is in the enum that is all. – John Foll Apr 08 '21 at 00:45
0

Found this useful. https://stackoverflow.com/a/64374930/16803533

no need to use IsDefined and No range checking

Areeba
  • 1