Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Iterating through all values of an ORed enum variable...

Iterating through all values of an ORed enum variable...

Scheduled Pinned Locked Moved C#
tutorialquestion
15 Posts 4 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P PhilDanger

    Well, I don't know how to iterate through all POSSIBLE values of an enum, but given that you say you do, I think I have a solution for you.

    Keys keys = Keys.Control | Keys.A;
    foreach(Keys key in POSSIBLEVALUES){ //however you're managing that
       if(keys & key) == key){ //the key contains this one!
    
        }
    }
    

    Note: the enum value have to be lined up in powers of 2 in order for this to work properly so you can distinguish the values when you do a bitwise-or. The following is a bit of code that shows this:

    enum Keys
            {
                A = 1,
                B = 2,
                C = 4,
                D = 8
            }
    
            static void Main(string[] args)
            {
                Keys keys = Keys.A | Keys.B | Keys.D;
                if ((keys & Keys.A) == Keys.A)
                {
                    Console.WriteLine("A");
                }
                if ((keys & Keys.B) == Keys.B)
                {
                    Console.WriteLine("B");
                }
                if ((keys & Keys.C) == Keys.C)
                {
                    Console.WriteLine("C");
                }
                if ((keys & Keys.D) == Keys.D)
                {
                    Console.WriteLine("D");
                }
    
    S Offline
    S Offline
    Shy Agam
    wrote on last edited by
    #6

    Yeah, well I guess that's the first solution I came up with too, but this would mean iterating through the entire enum, which in my case is very "expensive", as the Keys enum is quite large... :)

    1 Reply Last reply
    0
    • L Luc Pattyn

      Hi, first of all I hope your enum behaves as a flags collection (and hence it better have the [Flags] attribute). There is a very nice trick to enumerate the individual bits in an int without using a loop that checks each and every bit:

      int work=val; // copy the int whose bits need to be enumerated
      while (work!=0) {
      int singleBit=work & -work; // this has the lowest bit of work set
      work=work^singleBit; // removes work's lowest bit set
      ... do whatever you need to do with singleBit
      }

      Applied to enums, this leads to:

      [Flags]
      enum myFlags {a=1, b=2, c=4, d=8}

      public void Run() {
      myFlags flags=myFlags.a | myFlags.c | myFlags.d;
      int work=(int)flags; // copy the int whose bits need to be enumerated
      while (work!=0) {
      int singleBit=work & -work; // this has the lowest bit of work set
      work=work^singleBit; // removes work's lowest bit set
      myFlags mySingleFlag=(myFlags)singleBit;
      log(mySingleFlag.ToString());
      }
      }

      this little example prints the characters a, c and d as it should. :)

      Luc Pattyn


      try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


      S Offline
      S Offline
      Shy Agam
      wrote on last edited by
      #7

      Great! How do people come up with this stuff?! I can never get myself to think outside of the box like that! :doh: Anywayz... Why didn't Microsoft implement this kind of iteration too?? It can be very useful in some cases where you want to create something generic...

      L 2 Replies Last reply
      0
      • S Shy Agam

        Great! How do people come up with this stuff?! I can never get myself to think outside of the box like that! :doh: Anywayz... Why didn't Microsoft implement this kind of iteration too?? It can be very useful in some cases where you want to create something generic...

        L Offline
        L Offline
        Luc Pattyn
        wrote on last edited by
        #8

        Hi, casting back and forth between an enum and an int is standard practice; examples are everywhere, even in MS documentation. Tricky code snippets to manipulate bits (and do many other things), have been discovered one by one over time; I started my collection of those many years ago... I even have some books on them, some work only in assembly code, some only on specific processors, and some (like the current one) can be applied everywhere even in a high-level language. :)

        Luc Pattyn


        try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


        1 Reply Last reply
        0
        • S Shy Agam

          Great! How do people come up with this stuff?! I can never get myself to think outside of the box like that! :doh: Anywayz... Why didn't Microsoft implement this kind of iteration too?? It can be very useful in some cases where you want to create something generic...

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #9

          shyagam wrote:

          Why didn't Microsoft implement this kind of iteration too??

          You are absolutely right: they could have provided a GetEnumerator() method that would throw an exception if the enum is not [Flags], and returns an enumeration of the enum values that are present in the enum at hand. But they didnt. :)

          Luc Pattyn


          try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


          S 1 Reply Last reply
          0
          • L Luc Pattyn

            shyagam wrote:

            Why didn't Microsoft implement this kind of iteration too??

            You are absolutely right: they could have provided a GetEnumerator() method that would throw an exception if the enum is not [Flags], and returns an enumeration of the enum values that are present in the enum at hand. But they didnt. :)

            Luc Pattyn


            try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


            S Offline
            S Offline
            Shy Agam
            wrote on last edited by
            #10

            Luc Pattyn wrote:

            But they didnt.

            lol I guess that's a typical Microsoft-ic pattern... :laugh::laugh::laugh: Maybe they should have it copyrighted... ;P

            1 Reply Last reply
            0
            • L Luc Pattyn

              Hi, first of all I hope your enum behaves as a flags collection (and hence it better have the [Flags] attribute). There is a very nice trick to enumerate the individual bits in an int without using a loop that checks each and every bit:

              int work=val; // copy the int whose bits need to be enumerated
              while (work!=0) {
              int singleBit=work & -work; // this has the lowest bit of work set
              work=work^singleBit; // removes work's lowest bit set
              ... do whatever you need to do with singleBit
              }

              Applied to enums, this leads to:

              [Flags]
              enum myFlags {a=1, b=2, c=4, d=8}

              public void Run() {
              myFlags flags=myFlags.a | myFlags.c | myFlags.d;
              int work=(int)flags; // copy the int whose bits need to be enumerated
              while (work!=0) {
              int singleBit=work & -work; // this has the lowest bit of work set
              work=work^singleBit; // removes work's lowest bit set
              myFlags mySingleFlag=(myFlags)singleBit;
              log(mySingleFlag.ToString());
              }
              }

              this little example prints the characters a, c and d as it should. :)

              Luc Pattyn


              try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


              M Offline
              M Offline
              Martin 0
              wrote on last edited by
              #11

              Hello, So your solution would mean to iterate threw the enum members and do the bit test?

              Luc Pattyn wrote:

              (and hence it better have the [Flags] attribute).

              Is there a rule in the Framework when they use the Attribute?

              All the best, Martin

              L 2 Replies Last reply
              0
              • M Martin 0

                Hello, So your solution would mean to iterate threw the enum members and do the bit test?

                Luc Pattyn wrote:

                (and hence it better have the [Flags] attribute).

                Is there a rule in the Framework when they use the Attribute?

                All the best, Martin

                L Offline
                L Offline
                Luc Pattyn
                wrote on last edited by
                #12

                Hi Martin, [Flags] or [FlagsAttribute] is explained in the FlagsAttribute page on MSDN. It is rather long and not very important. One thing is it influences how ToString() works, which returns symbolic names when possible; with Flags it returns a combintation of one or more symbolic names, without Flags it does not. Unfortunately, when specifying [Flags] it still is possible to assign values that are NOT powers of 2 as in: [FlagsAttribute] enum myFlags3 { a=1, b=2, c=15, d=8 } In fact they do recommend you do this with the example Read=1, Write=2, ReadWrite=3 but I would like the possibility to get an error when I do this accidentally. Greetings. :)

                Luc Pattyn


                try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


                1 Reply Last reply
                0
                • M Martin 0

                  Hello, So your solution would mean to iterate threw the enum members and do the bit test?

                  Luc Pattyn wrote:

                  (and hence it better have the [Flags] attribute).

                  Is there a rule in the Framework when they use the Attribute?

                  All the best, Martin

                  L Offline
                  L Offline
                  Luc Pattyn
                  wrote on last edited by
                  #13

                  Hi,

                  Martin# wrote:

                  So your solution would mean to iterate threw the enum members and do the bit test?

                  No, my code does not even has to know what all the possible enum values are; the only thing it is interested in is the fact that they are Flags, not arbitrary values. Watch my while-loop carefully, it does not perform an Enum.GetValues() and it does not iterate over the bits (as in for(int bit=0; bit<32; bit++)...); it automatically loops a number of times, equal to the number of bits set in the enum value ! :)

                  Luc Pattyn


                  try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


                  M 1 Reply Last reply
                  0
                  • L Luc Pattyn

                    Hi,

                    Martin# wrote:

                    So your solution would mean to iterate threw the enum members and do the bit test?

                    No, my code does not even has to know what all the possible enum values are; the only thing it is interested in is the fact that they are Flags, not arbitrary values. Watch my while-loop carefully, it does not perform an Enum.GetValues() and it does not iterate over the bits (as in for(int bit=0; bit<32; bit++)...); it automatically loops a number of times, equal to the number of bits set in the enum value ! :)

                    Luc Pattyn


                    try { [Search CP Articles] [Search CP Forums] [Forum Guidelines] [My Articles] } catch { [Google] }


                    M Offline
                    M Offline
                    Martin 0
                    wrote on last edited by
                    #14

                    Fantastic, got it now! Again my '5' for that!

                    All the best, Martin

                    1 Reply Last reply
                    0
                    • S Shy Agam

                      Hello experts, Is there a way to iterate through all of the values assigned to an enum (in my case the Keys enum)? Something like: Keys keys = Keys.Control | Keys.A; foreach (Something goes here) // Do something with the key I know how to iterate through all POSSIBLE values of an enum, but I would like to iterate through all ASSIGNED values of an enum variable. Thanks in advance, Shy.

                      P Offline
                      P Offline
                      PhilDanger
                      wrote on last edited by
                      #15

                      FYI, here's another way to do it w/ Enum.Parse method, which is undoubtably slower and takes more memory, but improves readability (maybe :-D )

                              [Flags]
                              enum Keys
                              {
                                  A = 1,
                                  B = 2,
                                  C = 4,
                                  D = 8
                              }
                      
                              static void Main(string[] args)
                              {
                                  
                      
                                  Keys keys = Keys.A | Keys.B | Keys.D;
                                  string[] strKeys = keys.ToString().Split(',');
                                  foreach(string key in strKeys){
                                      Keys newKey = (Keys)Enum.Parse(keys.GetType(),key);
                                      Console.WriteLine(newKey.ToString());
                                  }
                              }
                      
                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups