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
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).
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());
}
}
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
}
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
}
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();
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
}