2016-09-27 6 views
0

Я в основном неправильно понимаю, как работает HasFlags? Я не понимаю, почему этот код терпит неудачу.Почему моя проверка флажком [Flag] Enum не работает?

Этот код принимает значение и определяет, является ли он действительной комбинацией значений моего Enum.

Две подгруппы значений Enum идентифицируются ORing другими членами: JustTheMonths и Exclusives. JustMonths объявляется в Enum, а Exclusives встроен в метод проверки.

Когда я передаю 1 или 2 (не назначенный или неизвестный) этому методу, он правильно идентифицирует их как действительные - эксклюзивы, но не члены JustTheMonths.

Но когда я передаю 4 этому коду, он правильно идентифицирует его как элемент всего набора, но неправильно идентифицирует его как члена подгруппы JustTheMonths.

Что я здесь делаю неправильно? Почему мой код считает, что 4 является членом (8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8172 | 16344)?

private void Form1_Load(object sender, EventArgs e) 
    { 
     FloweringMonth test = FloweringMonth.NotApplicable; 

     if (IsValidFloweringMonthValue((int)test)) 
     { 
      System.Diagnostics.Debug.WriteLine("Valid"); 
     } 
     else 
     { 
      System.Diagnostics.Debug.WriteLine("Not Valid"); 
     } 
    } 

    [Flags] 
    public enum FloweringMonth 
    { 
     Unassigned = 1, Unknown = 2, NotApplicable = 4, 
     Jan = 8, Feb = 16, Mar = 32, Apr = 64, May = 128, Jun = 256, 
     Jul = 512, Aug = 1024, Sep = 2048, Oct = 4086, Nov = 8172, Dec = 16344, 
     JustMonths = (Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec) 
    } 

    public static bool IsValidFloweringMonthValue(int value) 
    { 
     FloweringMonth incoming = (FloweringMonth)value; 

     FloweringMonth AllVals = FloweringMonth.Unassigned | FloweringMonth.Unknown | 
      FloweringMonth.NotApplicable | FloweringMonth.Jan | FloweringMonth.Feb | 
      FloweringMonth.Mar | FloweringMonth.Apr | FloweringMonth.May | 
      FloweringMonth.Jun | FloweringMonth.Jul | FloweringMonth.Aug | 
      FloweringMonth.Sep | FloweringMonth.Oct | FloweringMonth.Nov | FloweringMonth.Dec; 

     // does the incoming value contain any enum values from AllVals? 
     bool HasMembersOfAll = AllVals.HasFlag(incoming); 
     if (!HasMembersOfAll) return false; 

     // does the incoming value contain any enum values from JustTheMonths? 
     bool HasMembersOfMonths = FloweringMonth.JustMonths.HasFlag(incoming); 

     // does it contain any enum values from the set of three exclusive values? 
     FloweringMonth Exclusives = (FloweringMonth.Unassigned | 
      FloweringMonth.Unknown | FloweringMonth.NotApplicable); 
     bool HasMembersOfExclusives = Exclusives.HasFlag(incoming); 

     // an exclusive value cannot be mixed with any month values 
     if (HasMembersOfMonths && HasMembersOfExclusives) return false; // bad combo 

     // an exclusive value cannot be mixed with other exclusive values 
     if (incoming.HasFlag(FloweringMonth.Unassigned) && 
      incoming.HasFlag(FloweringMonth.Unknown)) return false; 
     if (incoming.HasFlag(FloweringMonth.Unassigned) && 
      incoming.HasFlag(FloweringMonth.NotApplicable)) return false; 
     if (incoming.HasFlag(FloweringMonth.Unknown) && 
      incoming.HasFlag(FloweringMonth.NotApplicable)) return false; 

     return true; 
    } 
+0

От https://msdn.microsoft.com/en-us/library/system.enum(v=vs.110).aspx: . . Определенные константы перечисления по степеням двух, то есть 1, 2, 4, 8 и т. Д. Это означает, что отдельные флаги в комбинированных константах перечисления не перекрываются. –

+0

@ m-y Um, no. Компилятор присваивает '0, 1, 2, 3, 4, ...' в отсутствие явных значений. Атрибут 'Flags' не изменяет этого поведения. –

+0

@ KennethK .: Я стою исправлен, вы правы. –

ответ

2

Ваши кратные 2 неверны. 4086 должен быть 4096, 8172 должен быть 8192 и т.д ...

+2

, чтобы избежать такой ошибки, используйте силу двух. Для ex: 'Unassigned = 2^0, Unknown = 2^1, NotApplicable = 2^2, Jan = 2^3, Feb = 2^4,' ... – kurakura88

+0

Бог. Как я мог это пропустить. Благодаря! Перестань делать мою собственную математику поздно ночью ... @ kurakura88, блестящая идея. –

+0

@ kurakura88 C# не имеет оператора PowerOf; то, что вы предложили ("^"), является побитовым оператором. Хороший тонкий жучок, который вы мне дали, это немного раскручивало. Необходимо использовать статический метод Math.Pow. Возможно, вы захотите отредактировать свой ответ, который я просто радостно скопировал в свой код :-) –

2

После @dukedukes ответа, проблема была там ваши кратны 2 были выключены.

Один из способов избежать этой ошибки - использовать операции bitwise с правой стороны.

[Flags] 
enum Months 
{ 
    January = 1 << 3, // 8 
    February = 1 << 4, // 16 
    March = 1 << 5, // 32 
} 
+2

Вы имели в виду '1 << 0' и' 1 << 1' и '1 << 2'? – zerkms

+0

@zerkms, да. я сделал. Благодарю. Я не использовал шаблон некоторое время. – Dennis

 Смежные вопросы

  • Нет связанных вопросов^_^