2014-10-29 2 views
0

Возможно, существует флаг, основанный в комбинации.Как перечислить перечисление, основанное на комбинации

Использование ProfileTypeFlag.SupplierMaster получить список только из "Поставщик | Master | External"

Я пытаюсь использовать этот код. Но они возвращают все перечисления;

public List<string> SetRoles(ProfileTypeFlag role) 
     { 
      List<string> result = new List<string>(); 
      foreach (ProfileTypeFlag r in Enum.GetValues(typeof(ProfileTypeFlag))) 
      { 
       if ((role & r) != 0) result.Add(r.ToString()); 
      } 

      return result; 
     } 


[Flags] 
public enum ProfileTypeFlag : uint 
    { 
     None = 0, 
     Customer = 1, 
     Supplier = 2, 
     Internal = 4, 
     Delegate = 8, 
     Master = 16, 
     External = 32, 
     CustomerMaster = Customer | Master | External, 
     SupplierMaster = Supplier | Master | External 
} 
+0

Хорошо ... Что вы * хотели, чтобы произошло? – BradleyDotNET

+0

вернуть список = «Поставщик», «Мастер», «Внешний» или список <Профили> с «Поставщиком», «Мастер», «Внешний» – AFetter

ответ

1

Вот решение для Вас:

public static string GetFlagsStringFromUInt32Enum<TEnum>(TEnum value) 
    where TEnum : struct 
{ 
    var sb = new StringBuilder(); 

    for(var i = 0; i < 32; ++i) 
    { 
     var bit = (uint)1 << i; 
     if (((uint)(object)value & bit) != 0) 
      sb.Append((TEnum)(object)bit).Append(" | "); 
    } 

    if (sb.Length > 0) 
     sb.Length -= 3; 

    return sb.ToString(); 
} 

Demo

Это будет работать на перечислений на основе uint, как ваша, я ddn't удосужились реализовать общее решение.

1

Просто немного подправить свой if заявление:

if ((role & r) == r && r != ProfileTypeFlag.None && role != r) 

Или вы могли бы использовать HasFlag (эквивалент role & r == r):

if (role.HasFlag(r) && r != ProfileTypeFlag.None && role != r) 

В принципе, если роль включает в себя флаг, это не флаг None, а не его роль, затем добавьте его в список.

Имея это в виду, вы могли бы изменить всю свою функцию:

public List<string> SetRoles(ProfileTypeFlag role) 
{  
    return 
     Enum.GetValues(typeof(ProfileTypeFlag)) 
      .Cast<ProfileTypeFlag>() 
      .Where(r => r != ProfileTypeFlag.None) 
      .Where(r => r != role) 
      .Where(r => role.HasFlag(r)) 
      .Select(r => r.ToString()) 
      .ToList(); 
} 

Как @Lucas отметил, что эти решения не работают вполне корректно, если ваше значение перечисления содержит составные флаги.

Одно решение это было бы удалить значения флагов, как вы сталкиваетесь с ними:

public List<string> SetRoles(ProfileTypeFlag role) 
{  
    var result = new List<string>(); 

    foreach (ProfileTypeFlag r in Enum.GetValues(typeof(ProfileTypeFlag))) 
    { 
     if (role.HasFlag(r) && r != ProfileTypeFlag.None) 
     { 
      result.Add(r.ToString()); 
      role &= ~r; 
     } 
    } 

    return result; 
} 
+0

+1 для фактической фиксации его кода. – BradleyDotNET

+0

Я предполагаю, что это сломается на что-то вроде 'ProfileTypeFlag.SupplierMaster | ProfileTypeFlag.Internal' –

+0

@LucasTrzesniewski: Вы правы, ваше решение может быть лучше. –

0

Чтобы обеспечить немного другой подход, вы можете использовать эту функцию, чтобы получить «набор» перечислений:

static IEnumerable<Enum> GetFlags(Enum input) 
{ 
    foreach (Enum value in Enum.GetValues(input.GetType())) 
     if (input.HasFlag(value)) 
      yield return value; 
} 

Кредит @Greg (Iterate over values in Flags Enum?)

Затем вызовите его как таковой:

List<string> names = GetFlags(enumValue).Select(e => e.ToString()).ToList(); 
Смежные вопросы