Отрицательные флаги в C # - PullRequest
       9

Отрицательные флаги в C #

8 голосов
/ 04 апреля 2011

Эй, есть ли способ хранить отрицательные флаги в C #?Например, у меня есть следующие перечисления флагов, которые представляют некоторые стили:

[Flags]
public enum Styles
{
    Default = 0,
    Bold = 1,
    Italic = 2
}

Теперь у меня есть несколько объектов, к которым могут быть применены эти стили, а затем все связанные элементы объединяются (т.е. другой объект может наследовать некоторый ранее установленныйстили).В дополнение к этому, я хотел бы определить отрицательные флаги, которые в основном отменяют унаследованные стили.Таким образом, если ранее стиль был установлен на Styles.Bold | Styles.Italic и объект наследует этот стиль, но имеет установленный отрицательный флаг Styles.Bold, то результат должен быть просто Styles.Italic.

. Есть ли механизм, который уже делаетэтот?Теперь я в основном придерживаюсь двух способов: во-первых, определяется NotXY перечислимых значений, которые затем каким-то образом анализируются для исключения значений XY, если они установлены.

Другой - просто определение двух полей, положительных и отрицательных флаговгде отрицательные флаги специально определены в дополнительном поле, и я получаю результирующие флаги, просто выполняя positiveFlags ^ negativeFlags.

edit:

Если это неясно, мне нужно сохранитькаждый из этих промежуточных стилей объектов.Например, это может быть так:

object1: Default
object2: Bold
object3: -Bold Italic

И если object3 также наследует значения 1 и 2, то конечный результат должен быть просто Italic.

Другой пример вответ на вопрос Кирен Джонстон, и согласно моему утверждению в комментарии, отрицательные значения применяются только на текущем уровне:

1: Bold
2: -Bold -Italic
3: Italic

2 удаляет жирный и курсивный из предыдущих объектов, но затем не должен применяться дальше(хотя положительные значения должны), поэтому окончательное значение снова будет Italic.

Ответы [ 4 ]

9 голосов
/ 04 апреля 2011

Так должен ли негатив всегда иметь приоритет? Что если вы начнете с NotBold, а затем добавите Bold?

Если при наличии он всегда переопределяется положительным на отрицательный, я бы предложил два поля:

private Styles baseStyles;
private Styles overrideDisableStyles;
public Styles ResultsStyles { return baseStyles & ~overrideDisableStyles; }

Или вы можете создать вспомогательный класс с SetStyle и UnsetStyle:

public void SetStyle(Styles styles)
{
    this.styles |= styles;
}

public void UnsetStyle(Styles styles)
{
    this.styles &= ~styles;
}

Для справки, positiveFlags ^ negativeFlags НЕ будет работать. Рассмотрим ситуацию, когда Bold не установлен, но NotBold установлен. Результат будет Bold, хотя единственным указанным флагом был NotBold.

Наконец, если вы делаете что-то коммерческое, углубленное, более сложное, чем вы описываете здесь, и хотите иметь расширяемое / расширяемое наследование стилей, вы должны правильно спроектировать его с помощью графов объектов / иерархии классов - начните с определения Style класс, который имеет один или несколько родительских объектов. Каждый Style может иметь набор пар имя / значение свойства, которые переопределяют что-либо из родительского объекта - может существовать коллекция Properties, которая возвращает эти переопределения, и метод Evaluate, который начинается с корневого объекта и перемещается к вопрос стиля, создание результирующего списка свойств для использования.

Надеюсь, это поможет.

2 голосов
/ 04 апреля 2011

Я бы порекомендовал пойти со вторым подходом.Это кажется мне более очевидным и простым.

1 голос
/ 02 мая 2011

Другое просто определяет два поля, положительные и отрицательные флаги, где отрицательные флаги специально определены в дополнительном поле, и я получаю результирующие флаги, просто выполнив positiveFlags ^ negativeFlags.

Это кажется наиболее естественным для меня (кроме выражения shoud, читаемого positiveFlags & ~negativeFlags). Кроме того, это приводит к простому методу применения унаследованных стилей. Если мы переписаем ваш пример

1: Bold
2: -Bold -Italic
3: Italic 

как (без специального синтаксиса ...)

1: pos:{ Bold }   neg:{ none }
2: pos:{ none }   neg:{ Bold Italic }
3: pos:{ Italic } neg:{ none }

тогда эффективные стили вычисляются с наследованием как (prevLevelStyle | pos) & ~neg, в результате чего:

1: ({ none } | { Bold })   & ~{ none }        = { Bold }
2: ({ Bold } | { none })   & ~{ Bold Italic } = { none }
3: ({ none } | { Italic }) & ~{ none }        = { Italic }

по желанию.

0 голосов
/ 04 апреля 2011

Если я не ошибаюсь, вам не нужно определять отрицательные флаги, но используйте "положительные" флаги для их сброса.

Например, этот код можно использовать для снятия флажка Полужирный

Styles styles = Styles.Bold | Styles.Italic;
styles = styles ^ Styles.Bold;
...