Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# .NET
I have an enum with flags attribute. How to check if int is in enum. Enum.IsDefiend returns false if check for example two ored values from enum.
Thanks in advance.
Posted 10-May-11 6:43am
apaka1.8K
Comments
John Simmons / outlaw programmer at 10-May-11 14:52pm
   
5 - Great question, btw.
Rick Shaub at 10-May-11 15:08pm
   
I agree it made me have to think outside the box.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 7

This is how to do it:
 
static bool IsIntInEnum(System.Type enumType, int value) {
   if (enumType == null) return false;
   if (!enumType.IsEnum) return false;
   var values = System.Enum.GetValues(enumType);
   if (values == null) return false;
   if (values.Length < 1) return false;
   foreach (object enumvalue in values)
       if (enumvalue is int) break; else return false;
   System.Predicate<int> predicate = (item) => { return (item & value) > 0; };
   return System.Array.Exists<int>((int[])values, predicate);
}
 
It is important to understand that the attribute System.FlagsAttribute only affects the string presentation of the value via ToString or string.Format. Also, with or without this attribute, enumeration members does not have to be powers of two. There are quite practical applications (in Windows API, for example) when the set of enumeration members represents the mixture of bit set values with, say, a set of consecutive values.
 
—SA
  Permalink  
v5
Comments
Rick Shaub at 10-May-11 21:54pm
   
I don't think this solves the OP's problem.
SAKryukov at 10-May-11 22:39pm
   
First, it's not yet complete. I have another variant, secondly -- arguments, please!
(I'll notify when it's done.)
--SA
SAKryukov at 10-May-11 22:42pm
   
Now it's done.
As far as I can see, this is the only correct solution on this page. You can test it.
--SA
Rick Shaub at 10-May-11 23:05pm
   
The OP wants to check if an int is bitwise OR of two or more flags, or a value in his enum. This solution will not do that. This type of iterative approach is going to be O(2^n) because you have to check all combinations of flags before declaring the result false. You could build a table and perform a binary search, which would be probably optimal timewise. Here's a simple test case:
 
[Flags]
public enum FlagEnum
{
one=1,
two=2,
four=4,
eight = 8,
sixteen =16,
thirtytwo = 32
 
}
private void button1_Click(object sender, EventArgs e)
{
bool orly = IsIntInEnum(typeof(FlagEnum),(int)(FlagEnum.one|FlagEnum.thirtytwo));
 
}
SAKryukov at 10-May-11 23:14pm
   
No, it won't, I agree. The question is formulated the way I'm not sure this is what is asked.
 
You see, FlagsAttribute has nothing to do with bitwise operations except presentation of the value by ToString. Moreover, enum members do not have to be the powers of 2. Perhaps this is the illusion of OP that it explains it. Until OP mentions explicitly a bit in a bit set, this is not either incorrectly formulated question or something what I did.
 
Finding if a bit is in enum is another simple task but I don't want to solve it until OP clear the question.
 
Anyway, thank you for this note, I'll modify the answer.
--SA
Rick Shaub at 10-May-11 23:16pm
   
He states clearly; " Enum.IsDefiend returns false if check for example two ored values...". This answer was already accepted, what's the problem? I don't think you understand the complexity. It's not simply find if a bit is in an enum, it's finding if an int matches any of the combination of bitwise ORs. My approach would work regardless of power-of-twos or not. I only used powers of twos to clearly demonstrate the principle. And FlagsAttribute has everything to do with bitwise OR. That's it's only purpose, to treat an enumeration as a bit field.
SAKryukov at 10-May-11 23:24pm
   
I got it. Answer updated.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

I know you've already accepted an answer, but here's a more math-oriented way (more code, too):
 
bool IsFlagsValid(Type t, int value)
{
    bool valid = false;
    if (t.IsEnum)
    {
        valid = true;
        int maxBit = Convert.ToInt32(Math.Pow(2, Math.Ceiling(Math.Log(value)/Math.Log(2)))) >> 2;
        int i = 1;
        do
        {
            if (0 != (value & (1 << i)))
            {
                valid = (Enum.IsDefined(t, 1 << i));
                if (!valid)
                {
                    break;
                }
            }
            i++;
        } while (maxBit > i);
    }
    return valid;
}
 
Call it like this:
 
if (IsFlagsValid(MyFlagsEnum, 25))
{
    // do something if the value was valid
} 
 
  Permalink  
v3
Comments
yesotaso at 10-May-11 15:24pm
   
What if... (just a thought)
[FlagsAttribute]
public enum psychoEnum
{ A = 0, B = 3, C = 4, D = 8 ... }
John Simmons / outlaw programmer at 10-May-11 15:33pm
   
For a Flags enum, 3 is not a valid ordinal, because if the enum value is set to 3, that means ordinals 1 and 2 are indicated. That's the way Flags enums work.
yesotaso at 10-May-11 15:50pm
   
Well yes 3 is not valid but it just compiles and runs :) Though I'd never do such thing knowingly.
SAKryukov at 10-May-11 20:05pm
   
3 is valid! FlagsAttribute only effect naming in ToString.
--SA
yesotaso at 10-May-11 20:43pm
   
Yes sir, syntactically and semantically but not figuratively.
Edit: I mean it boils down to habits again. Use of powers of 2 - checking against "logical and" etc..
BobJanova at 11-May-11 5:23am
   
It is valid:
[Flags]
enum SimpleExample { None = 0, Left = 1, Right = 2, Both = 3 }
SAKryukov at 10-May-11 20:03pm
   
John, I think there are some problem with this solution. Are you sure you do not assume the enumeration members are not always the powers of 2? They don't have to be. Using math for finding a maximum is not very elegant.
 
Please see my solution based on GetValues, I think it's free of these problems.
--SA
Rick Shaub at 11-May-11 9:38am
   
FYI from MSDN: "Guidelines for FlagsAttribute and Enum: ...
Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap. ..."
 
This basically means that while it's possible to define non power of two Flags-decorated enums, it is not recommended.
Ankur\m/ at 21-May-11 2:02am
   
I know it's old but...
I guess that comment was for SA. You clicked 'Add Comment' which will only notify the answerer. Use the reply link to reply to a particular user because that's the only way he will be notified. :thumbsup:
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Here's an article showing how to do what you are asking: 'Extending' the Enum Class to Validate the Enum Values with the Flags Attribute[^]. Unfortunately, this is not an easy fix.
 
Another slightly hacky alternative would be to take the result of .ToString() from your enum and call Int32.TryParse. If the result is true, that means the value is returning as an integer string, not a named enum or combination of enums.
 
//Example
int myThrowAwayInt;
MyEnum MyEnumValue = (MyEnum)2|8;
bool notDefined = Int32.TryParse(MyEnumValue.ToString(), out myThrowAwayInt);
if(notDefined)
{
    //This enum value is not defined
}
 
  Permalink  
v2
Comments
John Simmons / outlaw programmer at 10-May-11 14:33pm
   
Check out my version. :)
SAKryukov at 10-May-11 20:16pm
   
Nah! Please see correct solution.
--SA
Rick Shaub at 10-May-11 23:09pm
   
See my comment. Also note that I did not down vote.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Given the following enum I think what your looking for is DaysEnumNeedsFlags.Saturday.HasFlag(DaysEnumNeedsFlags.Saturday)
 
[FlagsAttribute]
public enum DaysEnumNeedsFlags
{
    None = 0,
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64,
    WeekDays = Monday | Tuesday | Wednesday | Thursday | Friday,
    Weekend = Saturday | Sunday
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 5

Heres an enum in C++/CLI that I am using to determine if columns on a grid have changed
 
[Flags] enum class m_FlagBits
{
        EXPIRY_ID = 1,
        DESCRIPTION = 2,
        EXPIRY_TYPE = 4,
        UNIT_ID = 8,
        FIXED_INTERVAL_ID = 16,
        DAY = 32,
        NUMBER_OF_INTERVAL_UNITS = 64,
        VALID_FROM = 128,
        VALID_TO = 256
};
m_FlagBits m_ElementList;
 

 
Make sure none of the values are set when I enter a row:
m_ElementList = m_ElementList & ~ m_FlagBits::EXPIRY_ID;
m_ElementList = m_ElementList & ~ m_FlagBits::EXPIRY_TYPE;
m_ElementList = m_ElementList & ~ m_FlagBits::DESCRIPTION;
m_ElementList = m_ElementList & ~ m_FlagBits::UNIT_ID;
m_ElementList = m_ElementList & ~ m_FlagBits::DAY;
m_ElementList = m_ElementList & ~ m_FlagBits::NUMBER_OF_INTERVAL_UNITS;
m_ElementList = m_ElementList & ~ m_FlagBits::FIXED_INTERVAL_ID;
m_ElementList = m_ElementList & ~ m_FlagBits::VALID_FROM;
m_ElementList = m_ElementList & ~ m_FlagBits::VALID_TO;
 

 
Setting one of them after changing a value:
m_ElementList = m_ElementList | m_FlagBits::EXPIRY_ID; 
 
Checking if one of them has been used
if (static_cast<int>(m_ElementList) & static_cast<int>(m_FlagBits::EXPIRY_ID))
{
   //Do Stuff like update the corresponding table
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 6

Once again, this is an answered question, but here's a hack-ish way to do this in very few lines of code. Full example below:
 
[Flags]
enum Nums
{
    One = 1,
    Two = 2,
    Four = 4
}
 
static void Main()
{
    Console.WriteLine(IsValidFlag<Nums>(3)); //true
    Console.WriteLine(IsValidFlag<Nums>(8)); //false
}
 
private static bool IsValidFlag<T>(int x) where T: struct
{
    return x.ToString() != ((T)(object)x).ToString();
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

You can check an or agains all numbers in decending order against your value and see if the result is zero.
 
static bool IsInNumbers(Type EnumType, int number) {
    var vals = Enum.GetValues(typeof(Numbers)).Cast<int>();
    for (int i = vals.Count() - 1; i >= 0; i--) {
        if ((vals.ElementAt(i) & number) == vals.ElementAt(i))
            number -= vals.ElementAt(i);
    }
        return number==0;
}</int>
 

comnplete example below
 
class Program {
    [Flags]
    public enum Numbers {
        Zero = 0,
        One = 1,
        Two = 2,
        Three = 4,
        Four = 8
    }
    static void Main(string[] args) {
        Type MyenumType = typeof(Numbers);
        Console.WriteLine(IsInNumbers(MyenumType, 1));
        Console.WriteLine(IsInNumbers(MyenumType, (int)(Numbers.Four | Numbers.Three)));
        Console.WriteLine(IsInNumbers(MyenumType, 9));
        Console.WriteLine(IsInNumbers(MyenumType, 23));
        Console.Read();
    }
 
    static bool IsInNumbers(Type EnumType, int number) {
        var vals = Enum.GetValues(typeof(Numbers)).Cast<int>();
        for (int i = vals.Count() - 1; i >= 0; i--) {
            if ((vals.ElementAt(i) & number) == vals.ElementAt(i))
                number -= vals.ElementAt(i);
        }
            return number==0;
    }
}
  Permalink  
Comments
cechode at 10-May-11 12:55pm
   
ouch a 1 vote ( heh )

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 277
1 Maciej Los 230
2 BillWoodruff 205
3 DamithSL 165
4 Sergey Alexandrovich Kryukov 155
0 OriginalGriff 5,130
1 DamithSL 4,157
2 Maciej Los 3,650
3 Kornfeld Eliyahu Peter 3,460
4 Sergey Alexandrovich Kryukov 2,811


Advertise | Privacy | Mobile
Web04 | 2.8.141216.1 | Last Updated 10 May 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100