Операторы перерасчета и вычитания
Кто-нибудь знает (и возможно: с каких пор) оператор -=
поддерживается в enum
значениях?
Я был счастливо кодирован сегодня, когда я по какой-то причине написал это, чтобы исключить значение из флагов enum
:
flags -= FlagsEnum.Value1;
После перечитывания и оценки моего кода я был удивлен тем, что он скомпилирован, фактически работал.
Записывая утверждение как
flags = flags - FlagsEnum.Value1
однако не компилируется.
Я не мог найти ничего в документации и в Интернете до сих пор. Кроме того, другие операторы (кроме операторов бит, конечно) не поддерживаются: +=
(включая флаг), *=
(пересечение в Pascal) не работают.
Это какой-то синтаксический сахар, встроенный в компилятор С#? Если да, то почему они решили не включать других операторов?
Простой пример кода:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication4
{
[Flags]
enum FlagsEnum
{
None = 0,
Value1 = 1,
Value2 = 2,
Value3 = 4
}
class Program
{
static void Main(string[] args)
{
FlagsEnum flags = FlagsEnum.Value1 | FlagsEnum.Value2 | FlagsEnum.Value3;
Console.WriteLine(flags);
flags -= FlagsEnum.Value1;
Console.WriteLine(flags);
flags -= FlagsEnum.Value3;
Console.WriteLine(flags);
flags -= FlagsEnum.Value2;
Console.WriteLine(flags);
Console.ReadLine();
}
}
}
Ответы
Ответ 1
Вычисление перечислений. Каждый тип перечисления неявно предоставляет следующий предопределенный оператор, где E - тип перечисления, а U - основной тип E:
U - (E x, E y);
Этот оператор оценивается точно как (U) ((U) x - (U) y). Другими словами, оператор вычисляет разницу между порядковыми значениями x и y, а тип результата является базовым типом перечисления.
источник
Надеюсь, вы знаете, что вы можете определить неявные значения для членов перечисления, поэтому, если вы дадите им значения x = 5, y = 10, z = 15, и вы попытаетесь сделать z-y, вы получите x.
Ответ 2
Iirc, -
по-прежнему является целым вычитанием.
Чтобы сделать исключение, вы хотите:
value = value & ~SomeEnum.Flag;
И включение:
value = value | SomeEnum.Flag;
Аналогично, для проверки частичного соответствия (любой бит от флага):
if((value & SomeEnum.Flag) != 0) {...}
Или полное совпадение (все биты в флаге):
if((value & SomeEnum.Flag) == SomeEnum.Flag) {...}