На жаль, вбудовані операції перерахування прапора .NET, на жаль, досить обмежені. Більшість часу користувачі залишаються розбиратися в бітовій логіці роботи.
У .NET 4 HasFlag
був доданий метод, Enum
який допомагає спростити код користувача, але, на жаль, з ним існує багато проблем.
HasFlag
не є безпечним для типу, оскільки він приймає будь-який тип аргументу значення enum, а не лише заданий тип enum.
HasFlag
неоднозначно, чи перевіряє, чи має значення цілий чи будь-який з прапорів, наданих аргументом значення enum. Це все до речі.
HasFlag
досить повільний, оскільки вимагає боксу, що спричиняє виділення і, таким чином, більше сміття.
Частково завдяки обмеженій підтримці .NET для переліків прапорців я написав бібліотеку OSS Enums.NET, яка вирішує кожну з цих проблем і полегшує справу з прапорцями.
Нижче наведено деякі операції, які він забезпечує разом з їх еквівалентними реалізаціями, використовуючи лише .NET-фреймворк.
Поєднайте прапори
.NET flags | otherFlags
Enums.NET flags.CombineFlags(otherFlags)
Видалити прапори
.NET flags & ~otherFlags
Enums.NET flags.RemoveFlags(otherFlags)
Загальні прапори
.NET flags & otherFlags
Enums.NET flags.CommonFlags(otherFlags)
Увімкніть прапори
.NET flags ^ otherFlags
Enums.NET flags.ToggleFlags(otherFlags)
Має всі прапори
.NET (flags & otherFlags) == otherFlags
абоflags.HasFlag(otherFlags)
Enums.NET flags.HasAllFlags(otherFlags)
Має якісь прапори
.NET (flags & otherFlags) != 0
Enums.NET flags.HasAnyFlags(otherFlags)
Отримати прапори
.NET
Enumerable.Range(0, 64)
.Where(bit => ((flags.GetTypeCode() == TypeCode.UInt64 ? (long)(ulong)flags : Convert.ToInt64(flags)) & (1L << bit)) != 0)
.Select(bit => Enum.ToObject(flags.GetType(), 1L << bit))`
Enums.NET flags.GetFlags()
Я намагаюся включити ці вдосконалення в .NET Core і, можливо, врешті-решт повну .NET Framework. Ви можете переглянути мою пропозицію тут .