c # Получать все значения перечисления больше заданного значения?

18

У меня есть следующее перечисление ролей членства:

public enum RoleName
{
    RegisteredUser,
    Moderator,
    Administrator,
    Owner
}

Я хочу иметь возможность извлекать все роли, больше или равные заданной роли.

Например, я ввожу Администратора, и я получаю IEnumerable с RoleName.Administration и RoleName.Owner

Что-то в этом роде:

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);
    }
}
    
задан bevacqua 24.07.2011 в 17:49
источник
  • , считая, что перечисление по умолчанию имеет тип INT, недостаточно для сравнения значений с фильтром int? –  Tigran 24.07.2011 в 17:53

7 ответов

13

Вы можете использовать следующий вспомогательный метод, чтобы дать вам набор ролей, разрешенных для данной роли:

    private IEnumerable<RoleName> AllAllowedRoles(RoleName level)
    {
        return Enum.GetValues(typeof(RoleName)).Cast<RoleName>().Where(role => level >= role);
    } 

И затем назначьте все из них пользователю.

    
ответ дан nakhli 24.07.2011 в 17:59
11

Вероятно, в зависимости от версии .NET. Но это очень хорошо для меня:

Нет необходимости конвертировать или использовать специальные трюки. Просто сравните с обычными операторами:

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();
    }
}
    
ответ дан Bitterblue 19.02.2014 в 12:05
7

, чтобы иметь лучшее определение , значение которого больше, чем другое, вам нужно назначить числовые значения следующим ролям:

public enum RoleName
{
    RegisteredUser = 2,
    Moderator = 4,
    Administrator = 8,
    Owner = 16
}

Теперь, если вы нажмете какой-либо экземпляр типа RoleName на (int), вы получите числовое значение и, следовательно, вы сможете сравнивать их друг с другом.

Примечание:
1. Здесь я использую полномочия 2 как значения, позволяющие комбинировать имена ролей с использованием бит-мудирующих операторов.

    
ответ дан Mo Valipour 24.07.2011 в 17:55
  • Неверно; вам не нужно назначать какие-либо значения. –  SLaks 24.07.2011 в 17:56
  • true, но, как я сказал: для того, чтобы иметь «лучшее определение». иначе вы можете легко запутаться. но, давая им ценности, вы всегда можете быстро это оценить. –  Mo Valipour 24.07.2011 в 17:58
  • Не уверен, что использование флагов здесь - хорошая идея. большинство комбинаций не имеют смысла, например. Владелец | Зарегистрированный пользователь. –  nakhli 24.07.2011 в 18:02
  • , это был просто дополнительный трюк. –  Mo Valipour 24.07.2011 в 18:05
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);
    }
    
ответ дан bevacqua 24.07.2011 в 18:17
0

Ваш код будет точно правильным, за исключением того, что вам нужно Cast<int>() , и вам не нужно ToList() .

    
ответ дан SLaks 24.07.2011 в 17:56
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;
    }

Вы можете проверить это Можете ли вы просмотреть все значения перечисления?     

ответ дан psu 24.07.2011 в 18:01
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);
}
    
ответ дан jason 24.07.2011 в 18:09
  • Является ли отражение действительно лучшим способом? –  bevacqua 24.07.2011 в 18:14
  • @Nico: Если вы хотите, чтобы он был общим, да. Если вы хотите его ТОЛЬКО для RoleName, нет. –  jason 24.07.2011 в 18:53