Есть ли способ необязательно форматировать перечисление [Flags]
как «не-флаги» для определенных целей?Использовать флаги Enum в качестве обычного Enum
Например, у меня есть
enum MyEnum {
X ,
Y ,
Z
}
Теперь, скажем, у меня есть два класса A
и B
. Класс B будет в основном использоваться в пределах IEnumerable<B>
. Класс A отвечает за разбор этого списка, но только тогда, когда перечисление соответствует определенному значению;
class B {
MyEnum MyProperty { get; set; }
}
class A {
MyEnum Target = MyEnum.C;
void DoSomething(IEnumerable<B> list) {
for (var b in list) {
if (b.MyProperty == this.Target) {
// Do Some Work
}
}
}
}
Теперь предположим, что я хочу, класс А, чтобы иметь возможность работать с несколькими типами B. Я мог бы добавить [Flags] атрибут моего перечисления и сделать что-то вроде этого:
[Flags]
enum MyEnum {
None = 0,
X = 1,
Y = 2,
Z = 4
}
class B {
MyEnum MyProperty { get; set; }
}
class A {
MyEnum Target = MyEnum.X | MyEnum.Z;
void DoSomething(IEnumerable<B> list) {
for (var b in list) {
if (this.Target.HasFlag(b.MyProperty)) {
// Do Some Work
}
}
}
}
Однако, класс B's MyProperty
теперь может использоваться как флаг, что является проблемой, поскольку в контексте B.MyProperty
нет такой вещи, как MyEnum.X | MyEnum.Y
. Это имеет смысл в A
, потому что я целенаправленное воздействие на различные виды класса B.
Обходной, что я придумал это:
enum MyEnum {
None = 0,
X = 1,
Y = 2,
Z = 4
}
[Flags]
enum MyEnumTarget {
None = 0,
X = 1,
Y = 2,
Z = 4
}
class B {
MyEnum MyProperty { get; set; }
}
class A {
MyEnumTarget Target = MyEnumTarget.X | MyEnumTarget.Z;
void DoSomething(IEnumerable<B> list) {
for (var b in list) {
if (this.Target.HasFlag((MyEnumTarget)b.MyProperty)) {
// Do Some Work
}
}
}
}
В то время как это работает, это, безусловно, грязное. Теперь мне нужно отслеживать два разных перечисления. Любое изменение, которое я делаю в одном, я должен сделать в другом, и я должен убедиться, что значения синхронизированы. Кроме того, теперь мне нужно отправить MyEnumTarget
, чтобы передать значение Enum.HasFlag
. Конечно, я мог бы выполнять побитые операции, но тогда это не всегда так очевидно, что это за намерение. В любом случае, мне все равно потребуется два «совпадающих» перечисления.
Нет ли лучшего способа сделать это? Можно ли использовать один тип перечисления и заставить какой-то атрибут [NoFlags] на B.MyProperty
. Или есть два перечисления, которые считаются наилучшим способом/хорошей практикой?
Я использую C# 6.0, если это имеет значение
Имейте в виду, что флаги перечислены или нет, * любое * целочисленное значение может быть введено в значение типа 'MyEnum'. Вам необходимо проверить значения, с которыми вы работаете, в любом случае. Перечисления не ограничены только определенными значениями. –
Я знаю, что любое целое может быть применено к этому. Однако я не беспокоюсь о том, чтобы кто-то присвоил ему ценность. Все это является внутренним для сборки и не подвергается никому другому. Внутри мы знаем, как его использовать, и по существу не будем злоупотреблять свойствами ... его больше как предосторожность для тех, кто вносит изменения в будущем. – pinkfloydx33