Click here to Skip to main content
15,169,285 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I assign flags to an enum variable and want:
1.- Retrieve their values without iterating on the Enum typeof and check if the variable has the flag with HasFlag. That is, I want to iterate over the Variable retrieving its Flags. For example, if I assign flags to a variable and stop execution and check the variable with Debug, its flags appear.

2.- Retrieve the values in the Order in which I have assigned them. Suppose I want to do something in the order in which I have entered the flags.

C#
namespace Name_Enum_Test
{
    #region Inicializacion
    [System.Flags]
    public enum Enum_Test
    {   Undefined  = 0,
        One        = 1,
        Two        = 2,
        Tree       = 4
    }
    public class Cls_Enum_Test
    {
    #endregion

    #region Enum. Test
        // --------------------------------------------------
        // ENUM. TEST.
        // Ejemplo:Name_Enum_Test.Cls_Enum_Test.Fcn_Test(Name_Enum_Test.Enum_Test.Two | Name_Enum_Test.Enum_Test.One)
        // --------------------------------------------------
        // [System.Diagnostics.DebuggerStepThroughAttribute]
        public static void Fcn_Test(Name_Enum_Test.Cls_Enum_Test Enum_Test)
        {  
            try
            {   foreach(System.Enum MyEnum in Enum_Test)
                {
                }
            }
            catch(System.Exception ErrorExcp){}
        }
    }
    #endregion
}


What I have tried:

in this function.in this function.in this function.
Posted
Updated 7-Oct-21 6:43am
v2

1) You can't. The closest you can get is to use Enum.GetValues combined with Enum.HasFlag:
C#
public static class EnumExtensions
{
    public static IEnumerable<T> ListFlags<T>(this T value) where T : struct, Enum
    {
        // Check that this is really a "flags" enum:
        if (!Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
        {
            yield return value;
            yield break;
        }
        
        T[] values = (T[])Enum.GetValues(typeof(T));
        for (int index = 0; index < values.Length; index++)
        {
            T flag = values[index];
            if (!flag.Equals(default(T)) && value.HasFlag(flag))
            {
                yield return flag;
            }
        }
    }
}


2) You can't. The Enum is simply a numerical value representing the combined values of the specified flags. It does not maintain any information about the order in which they were added.

For a literal assignment, the compiler doesn't even preserve the combining operation. Code such as:
C#
Enum_Test value = Enum_Test.One | Enum_Test.Two;
is compiled to:
C#
Enum_Test value = (Enum_Test)3;

If the order in which the flags were set is important to you, then an Enum is the wrong tool to use.
   
v2
Comments
BillWoodruff 7-Oct-21 10:07am
   
+5 really appreciate the information about what happens at compile time
An enum is stored as an integer, so you can cast between them at will.
So you can use the binary AND, OR, XOR, and NOT operators to check your values very easily:
C#
Enum_Test et = Enum_Test.One | Enum_Test.Two;
if ((et & Enum_Test.Two) == 0)
{
    Console.WriteLine("Two is not set");
}
else
{
    Console.WriteLine("Two is set");
}
   
1. Yes and no. You may have to iterate the defined values, but you definitely don't want to do so many times during the execution of the application, especially in a loop.
What I prefer to do is to populate a Dictionary once at the startup, in a static class or similar, then access the Dictionary as needed.

2. If you really want to, then you'll have to develop support for it. Maybe your class can use a Stack of enum values rather than a single value. When a value is set, you push the new value onto the Stack. Then you can walk the Stack to determine the order of set values.
   
Advice; I think you need to "ground" your understanding of what Enums are, and what they are intended to be used for with some research and careful experimentation. Here's some great tutorials: [^], [^]

Caution: Enums are single/special purpose entities that are compiled into an internal form: you have to use reflection on Type (expensive methods) to access its internals ... compared to other structures. Enums conveniently embody the idea of a set of values related by magnitude.

I can see no reason why anyone would want/need to determine whether an Enum had the Flags attribute at run-time ... if I saw code performing that test, I'd say there is a problem in the strategy/structure being used.

As Piebald noted above, the Flags Attribute only affects certain Enum functions: ToString, Enum.Parse, and Enum.IsDefined.

If an Enum has #0 CustomAttributes, it is not flagged; but an Enum could have one, or more, CustomAttributes, and not be flagged.

You can determine if an Enum has Flags at run-time:
public bool HasflagsAttribute(Type enm)
{
    return enm.IsDefined(typeof(FlagsAttribute), false);
}

// test
//    enum test1
//    {
//        notokay = 1,
//        okay = 2,
//        good = 4
//    }
//
//    [Flags]
//    enum test2
//    {
//        notokay = 1,
//        okay = 2,
//        good = 4
//    }
//
//    bool test1flagged = HasflagsAttribute(typeof(test1));
//    bool test2flagged = HasflagsAttribute(typeof(test2));
   

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




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900