2013-02-11 3 views
1

я получил следующее заявлениеНастройка всех значений флага перечисления за исключением одного поля

private uint mask; 
Action<FlagEnum> setField = new Action<FlagEnum>(x => this.mask = (uint)x); 

и следующее перечисление, например:

[Flags] 
public enum FlagEnum : uint 
{ 
    Clear = 0x0, 
    F1 = 0x1, 
    F2 = F1 << 1, 
    F3 = F2 << 1, 
    F4 = F3 << 1, 
    F5 = F4 << 1, 
    F6 = F5 << 1 
} 

Теперь я хочу, чтобы установить все флажки, кроме флага «Очистить». Я попытался это:

setField(!FlagEnum.Clear); 

Но я получаю следующее сообщение

Operator '!' cannot be applied to perand of type 'BitMask.FlagEnum' 

Установка флага, например:

setField(FlagEnum.F1) 

работает отлично.

Итак, вопрос в том, как я могу установить все поля FlagEnum вместо «Clear» с моим подходом? Или это невозможно, и я должен выполнить это требование.

ответ

2

В вашем конкретном случае FlagEnum.Clear установлен на ноль, что означает, что он не может быть «установлен». Ваши флаги определены следующим образом (сокращено до 8 бит):

Clear = 00000000 
F1 = 00000001 
F2 = 00000010 
F3 = 00000100 
F4 = 00001000 
F5 = 00010000 
F6 = 00100000 

Так что, если, скажем, F2, F3 и F5 объединяется, двоичное представление вашего значения будет 00010110 - это комбинация, полученная из побитовое ИЛИ этих трех флагов.

Однако, как должно быть добавлено Clear? Clear равно нулю, поэтому ORing его к значению ничего не изменит. Вместо этого, только если ни один из других флагов не установлен, ваше значение будет автоматически Clear.

Если вы этого не хотите, начните с назначения 0x01 на Clear.


Как правило, вы действительно можете удалить одно значение из ваших флагов переменной, и ваша идея о отрицая значение флага было правильно - только что в C#, побитовое НЕ выражается тильды (~), а не восклицательный знак, используемый для логического не.

Таким образом, инвертированная битовая диаграмма F2 равна 11111101. Чтобы удалить F2 с 00010110, OR не будет, потому что результат будет 11111111. Вместо этого отрицательное значение должно быть ANDed с предыдущей комбинацией флагов:

00010110 & 11111101 = 00010100 (F3, F5) 
+0

Спасибо за этот раунд. Пока что моя реализация работает хорошо. У меня есть операция OR, AND & XOR. Теперь, что нужно делать, 'setField (! FlagEnum.Clear);' должен просто установить все биты от 0 до 1 и оставить 1 неизменным. Как метод под названием 'FillField()' ** bold ** okay, я нашел его: 'this.mask = ~ (uint) FlagEnum.Clear'did трюк –

+0

@DanielW.: Лично я бы подумал о добавлении в константу 'enum 'еще одной константы, которая явно указала бы, что все определенные значения будут более чистыми, но, конечно, для этого требуется еще несколько строк кодирования. В любом случае, пожалуйста, выберите ответ как выбранный, если он вам помог, или, иначе, не стесняйтесь спрашивать дальше. –

0

Следующее O.R. Картонный подход Я решил это так:

/// <summary> 
    /// Operates the specified flag. 
    /// </summary> 
    /// <param name="flag">The flag.</param> 
    /// <param name="operation">The operation.</param> 
    public void Operate(FlagEnum flag, OperationEnum operation) 
    { 
     this.flag = flag; 
     switch (operation) 
     { 
      case OperationEnum.AND: 
       operate((x, y) => x & y); 
       break; 
      case OperationEnum.OR: 
       operate((x, y) => x | y); 
       break; 
      case OperationEnum.XOR: 
       operate((x, y) => x^y); 
       break; 
      case OperationEnum.NOT: 
       throw new NotImplementedException("The operation 'NOT' is not implemented so far!"); 
     } 
    } 

/// <summary> 
    /// Operates the specified operation. 
    /// </summary> 
    /// <param name="operation">The operation.</param> 
    private void operate(Func<uint, uint, uint> operation) 
    { 
     this.Mask = operation(this.Mask, (uint)this.flag); 
    } 

    /// <summary> 
    /// Clears the mask. 
    /// </summary> 
    public void ClearMask() 
    { 
     this.Mask = (uint)FlagEnum.Clear; 
    } 
Смежные вопросы