C# 将标记的枚举解析为列表的最有效方法
我有一个标记的枚举,需要检索它上设置的所有值的名称 我目前正在利用enum的ToString()方法,该方法返回逗号分隔的元素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
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
}