C# 将标记的枚举解析为列表的最有效方法

C# 将标记的枚举解析为列表的最有效方法,c#,enums,C#,Enums,我有一个标记的枚举,需要检索它上设置的所有值的名称 我目前正在利用enum的ToString()方法,该方法返回逗号分隔的元素 public void SetRoles(Enums.Roles role) { IList<Entities.Role> roleList = role.ToString("G").Split(',') .Select(r => new Entities.Role(r.Trim())) .T

我有一个标记的枚举,需要检索它上设置的所有值的名称

我目前正在利用enum的ToString()方法,该方法返回逗号分隔的元素

public void SetRoles(Enums.Roles role)
{
    IList<Entities.Role> roleList = role.ToString("G").Split(',')
        .Select(r => new Entities.Role(r.Trim()))
        .ToList();
    ...
}
public void SetRoles(Enums.Roles角色)
{
IList roleList=role.ToString(“G”).Split(“,”)
.Select(r=>newentities.Role(r.Trim()))
.ToList();
...
}

我相信一定有比这更好的办法。

你为什么需要一份清单?所有内容都已存储在标志中:

[Flags]
enum Roles
{
    Read = 0x1,
    Write = 0x2,
    Delete = 0x4,
}
然后分配角色:

var roles = Roles.Read | Roles.Write;
当您需要检查某个给定角色是否已被删除时,不需要查看列表,只需查看角色枚举:

if ((roles & Roles.Read) == Roles.Read)
{
    // The user has read permission
}
if ((roles & Roles.Write) == Roles.Write)
{
    // The user has write permission
}
试试这个:

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());
  }
}
public void SetRoles(Enums.Roles角色)
{
列表结果=新列表();
foreach(Enum.GetValues中的角色r(typeof(角色)))
{
如果((角色&r)!=0)结果。添加(r.ToString());
}
}

Enum.Parse将很好地处理ToString输出的连接值。使用即时窗口进行验证:

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

(第二行是输出,它在调试器/即时窗口中不同于一般的Enum.ToString()输出)。

如果您真正想要字符串,那么最简单的就是:

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

这比使用LINQ更简单,仍然只是一行代码。 或者,如果您想要列表而不是问题示例中的数组,您可以将数组转换为列表:

List flags=新列表(role.ToString().Split(',')

在我的情况下,我需要一个通用的解决方案,并提出了以下建议:


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

与Mick的答案类似,但将操作放入扩展中,修复/清除多余的空格字符(从拆分中)

另外,如果枚举中有一个
\uuu
,则代码会将其更改为一个空格

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('_', ' ');
}
List GetRoleNames(角色)=>
Enum.GetValues(类型(角色))
.Cast()
.Where(角色=>roles.HasFlag(角色))
.Select(角色=>role.ToString())
.ToList();
void TestRoleSelection()
{
变量selectedRoles=(角色)6;
var roleNames=GetRoleNames(selectedRoles);
Console.WriteLine(string.Join(“,”,roleNames));
//输出:管理员,用户
}
[旗帜]
枚举角色
{
超级管理员=1,
管理员=2,
用户=4,
匿名=8
}

这就是应用程序使用它的方式。然而,这更多的是一个持续关注的问题。我宁愿让此方法不知道枚举可能包含哪些值。如果是为了持久性,则只需要存储一个表示标志的整数,因为此整数允许您稍后提取所有角色。不需要存储列表。否则,如果要保留角色列表,则不需要使用
[Flags]
。您还将获得几个字节的存储介质:-)但是,有时将存储的数据保持为人类可读的格式很重要。在这种情况下,Enum.Parse可以很好地处理连接的枚举值,类似于ToString()输出它们的方式。因此
Enum.Parse(typeof(Roles),“Read,Write”)
将生成正确的读写值。事实上,我会用这些信息来写一个答案。@David,这本书的要点是它允许你将多个值存储到一个整数中。我同意David的观点。虽然标志枚举的功能是将多个设置连接到一个值中,但有时人类可读性优于紧凑性。1064的价值是多少?好的,1024&32&8,但是这些值是什么意思?您是否知道要拆分标志,或者您是否认为这只是一些预定义的单一状态代码?您必须检查代码,或者类似地提供一些必须找到并读取的值的文档。空间便宜;将其存储为“读、写、删除”,处理原始数据的人可以一目了然地理解它。最好替换
(role&r)!=0
与.net4中的
(角色&r)=r
角色.HasFlag(r)
。并确保指定的值是2的幂,否则它将失败。请参阅此处的同一行版本:
Enum.GetValues(typeof(Roles)).Cast()。其中(r=>(role&r)==r)。选择(r=>r.ToString())
,而不是if((role&r)!=0)使用role.HasFlag(r)有两个原因:1)假设枚举中的值等于0。对于您的代码,该值将始终出现在列表中,无论您有什么组合。2) 现在,如果在枚举中有一个组合,列表将计算单个元素和相应的组合。最佳答案。非常感谢。除非它甚至不能正常工作——它在所有列表元素上都添加了一个空格,但第一个元素除外,因为要拆分的
ToString()
生成的列表中逗号后有一个空格。如果不需要任何空格,只需添加一行“result=result.Replace”(“,”)'问题没有说明逗号后面不能有空格!这是一个初学者级别的修复,可以删除空格。必须包含如何执行此操作或说解决方案因此无法工作似乎很愚蠢。很高兴知道存在类似的情况-
enum的ToString()方法返回逗号分隔的元素。你让我开心:)+1.
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" }
[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
}
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
}