C#获取所有枚举值大于给定值的方法?

23
我有以下成员角色的枚举:
public enum RoleName
{
    RegisteredUser,
    Moderator,
    Administrator,
    Owner
}

我希望能够获取所有大于或等于给定角色的角色。

例如,我输入“管理员”,然后获得一个包含RoleName.AdministrationRoleName.OwnerIEnumerable

需要实现类似这样的功能:

public static void AddUserToRole(string username, RoleName level)
{
    var roles = Enum.GetValues(typeof(RoleName)).Cast<R>().ToList().Where(role => level > role);

    foreach (var role in roles)
    {
        Roles.AddUserToRole(username, role);
    }
}

1
考虑到枚举默认为 INT 类型,仅将其值与 int 过滤器进行比较是否足够? - Tigran
7个回答

24

可能取决于.NET的版本。但是对我来说这很有效:

无需转换或使用特殊技巧,只需使用通常的运算符进行比较即可:

using System;

enum Test { a1, a2, a3, a4 }

class Program
{
    static void Main(string[] args)
    {
        Test a = Test.a2;

        Console.WriteLine((a > Test.a1));
        Console.WriteLine((a > Test.a2));
        Console.WriteLine((a > Test.a3));
        Console.WriteLine((a > Test.a4));

        Console.ReadKey();
    }
}

输出:

True
False
False
False

20
你可以使用以下帮助方法来为给定的角色提供一组允许的角色:
    private IEnumerable<RoleName> AllAllowedRoles(RoleName level)
    {
        return Enum.GetValues(typeof(RoleName)).Cast<RoleName>().Where(role => level >= role);
    } 

然后将它们全部分配给用户。


7
为了更好地定义哪个角色比另一个更重要,您需要给您的角色分配如下的数字值:
public enum RoleName
{
    RegisteredUser = 2,
    Moderator = 4,
    Administrator = 8,
    Owner = 16
}

现在,如果你将任何一种类型的RoleName实例转换为(int),你将获得数字值,因此你将能够相互比较它们。

注意:
1. 在这里,我使用2的幂作为值,以允许使用位运算符组合RoleNames。


5
错误,您不需要分配任何值。 - SLaks
1
没错,但正如我所说:为了有一个“更好的定义”。否则你很容易会感到困惑。但是通过给它们赋值,你总是可以快速判断的。 - Mo Valipour
1
不确定在这里使用标志是一个好主意。大多数组合都没有意义,例如Owner | RegisteredUser。 - nakhli

2

使用了这个:

    public static void AddUserToRole(string username, RoleName level)
    {
        var roles = RolesLesserThanOrEqualTo(level);

        foreach (var role in roles)
        {
            Roles.AddUserToRole(username, role.Name());
        }
    }

    public static IEnumerable<RoleName> RolesLesserThanOrEqualTo(RoleName level)
    {
        return Enum.GetValues(typeof(RoleName)).Cast<RoleName>().Where(role => level >= role);
    }

0
public enum RoleName : int
{
    RegisteredUser = 7,
    Moderator = 8,
    Administrator = 9,
    Owner = 10
}

 public List<RoleName> GetGreaterOrEqual(RoleName role)
    {
        List<RoleName> list = new List<RoleName>();
        foreach (RoleName rn in Enum.GetValues(typeof(RoleName)))
        {
            if(rn >= role)
                list.Add(rn);
        }
        return list;
    }

你可以查看这个 你能循环遍历所有枚举值吗?

0

你必须考虑枚举的底层类型。因此:

static IEnumerable<T> Get<T>(T value) where T : struct {
    Type underlyingType = Enum.GetUnderlyingType(typeof(T));
    var compareToMethod = underlyingType.GetMethod(
                              "CompareTo",
                              new[] { underlyingType }
                          );
    var values = Enum.GetValues(typeof(T));
    for (int index = 0; index < values.Length; index++) {
        int comparison = (int)compareToMethod.Invoke(
            Convert.ChangeType(value, underlyingType),
            new object[] { values.GetValue(index) }
        );
        if (comparison >= 0) {
            yield return (T)values.GetValue(index);
        }
     }
 }

我不想费心想出一个好名字,但这个可以用:

var largerValues = Get<RoleName>(RoleName.Moderator);
foreach(var largerValue in largerValues) {
    Console.WriteLine(largerValue);
}

反射真的是最好的选择吗? - bevacqua
@Nico:如果你想让它变得通用,那么是的。如果你只想针对“RoleName”,那就不行。 - jason

0

你的代码完全正确,只需要使用Cast<int>()而不需要使用ToList()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接