Операторы перерасчета и вычитания

Кто-нибудь знает (и возможно: с каких пор) оператор -= поддерживается в 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) {...}