Most efficient way to parse a flagged enum to a list

前端 未结 6 1363
猫巷女王i
猫巷女王i 2021-01-01 09:06

I have a flagged enum and need to retrieve the names of all values set on it.

I am currently taking advantage of the enum\'s ToString() method which returns the eleme

相关标签:
6条回答
  • 2021-01-01 09:25

    Enum.Parse will handle the concatenated values outputted by ToString just fine. Proof using the Immediate window:

    ? System.Enum.Parse(typeof(System.AttributeTargets), "Class, Enum")
    Class | Enum
    

    (the second line is the output, which is different in the debugger/immediate window from the generic Enum.ToString() output).

    0 讨论(0)
  • 2021-01-01 09:28

    Try this:

    public void SetRoles(Enums.Roles role)
    {
      List<string> result = new List<string>();
      foreach(Roles r in Enum.GetValues(typeof(Roles))
      {
        if ((role & r) != 0) result.Add(r.ToString());
      }
    }
    
    0 讨论(0)
  • 2021-01-01 09:30
    List<string> GetRoleNames(Roles roles) =>
        Enum.GetValues(typeof(Roles))
            .Cast<Roles>()
            .Where(role => roles.HasFlag(role))
            .Select(role => role.ToString())
            .ToList();
    
    void TestRoleSelection()
    {
        var selectedRoles = (Roles)6;
        var roleNames = GetRoleNames(selectedRoles);
        Console.WriteLine(string.Join(",", roleNames));
        // Output: Admin,User
    }
    
    [Flags]
    enum Roles
    {
        SuperAdmin = 1,
        Admin = 2,
        User = 4,
        Anonymous = 8
    }
    
    0 讨论(0)
  • 2021-01-01 09:36

    Why do you need a list? Everything is already stored in the flags:

    [Flags]
    enum Roles
    {
        Read = 0x1,
        Write = 0x2,
        Delete = 0x4,
    }
    

    Then assign roles:

    var roles = Roles.Read | Roles.Write;
    

    And whenever you need to check if a given role has been you don't need to look in a list, but simply look in the roles enumeration:

    if ((roles & Roles.Read) == Roles.Read)
    {
        // The user has read permission
    }
    if ((roles & Roles.Write) == Roles.Write)
    {
        // The user has write permission
    }
    
    0 讨论(0)
  • 2021-01-01 09:38

    If you genuinely just want the strings, can't get much simpler than:

    string[] flags = role.ToString().Split(',');

    This is simpler than using LINQ and is still just a single line of code. Or if you want a list instead of an array as in the sample in the question you can convert the array into a list:

    List<string> flags = new List<string>(role.ToString().Split(','));

    In my case I needed a generic solution and came up with this:

    value.ToString().Split(',').Select(flag => (T)Enum.Parse(typeof(T), flag)).ToList();

    0 讨论(0)
  • 2021-01-01 09:41

    Similar answer to Mick's but puts the operations into extensions and fixes/cleans up the extra space character (from the split).

    Also as a bonus if the enum has a _ in it, the code changes it to a space.

    public static class EnumExtensions
    {  
        // Take anded flag enum and extract the cleaned string values.
        public static List<string> ToComparableStrings(this Enum eNum)
            =>  eNum.ToString()
                    .Split(',')
                    .Select(str => str.ToCleanString())
                    .ToList();
    
        // Take an individual enum and report the textual value.
        public static string ToComparableString(this Enum eNum)
            => eNum.ToString()
                   .ToCleanString();
    
        // Remove any spaces due to split and if `_` found change it to space.
        public static string ToCleanString(this string str)
            => str.Replace(" ", string.Empty)
                  .Replace('_', ' ');
    }
    

    Usage

    var single   = PivotFilter.Dollars_Only;
    var multiple = PivotFilter.Dollars_Only | PivotFilter.Non_Productive;
    
                                    // These calls return:
    single.ToComparableString()     // "Dollars Only"
    multiple.ToComparableString()   // "Non Productive,Dollars Only"
    multiple.ToComparableStrings()  // List<string>() { "Non Productive", "Dollars Only" }
    

    Enum for Usage

    [Flags]
    // Define other methods, classes and namespaces here
    public enum PivotFilter
    {
        Agency = 1,
        Regular = 2,
        Overtime = 4,
        Non_Productive = 8,
        Dollars_Only = 16,
        Ignore = 32
    }
    
    0 讨论(0)
提交回复
热议问题