Перечисление флагов и битовые операции по сравнению со “строкой битов”

Новое размещение может использоваться для создания безопасных с точки зрения типов объединений, таких как Повышение variant.

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

35
задан Eric 15 March 2013 в 15:28
поделиться

6 ответов

Преимущества использования Flags enum:

Недостатки использования Flags enum:

  • Представление данных для людей трудно понять (например, какие флаги установлены для 17?)


Преимущества использования строки битов:

  • Программистам легко увидеть, какие биты установлены в строке

Отрицательные стороны использования строка битов:

  • Нестандартный подход
  • Труднее понять программистам, незнакомым с вашим дизайном
  • Потенциально проще установить «мусорные» значения (например, stringValue = «Sunday»)
  • Создание ненужной строки
  • Излишний синтаксический анализ строки
  • Дополнительные разработки
  • Новое изобретение колеса (но даже не круглого колеса)


Насколько важно иметь возможность смотреть на строку битов, чтобы увидеть, что установлено? Если сложно понять, что 17 - это понедельник и пятница, вы всегда можете использовать калькулятор и преобразовать в двоичный формат. Или добавьте какое-то строковое представление для "отображения" (или отладка) использовать. Это не , что сложно.


Мне также кажется, что если вы собираетесь сделать последовательность битов более цельной, тогда вам нужно будет сделать небольшую инкапсуляцию, чтобы довести ее до уровня абстракции, которую уже предоставляет перечисление Flags. Если подход состоит в том, чтобы просто манипулировать строкой битов напрямую, тогда это будет трудно прочитать (и понять) и, вероятно, будет подвержено ошибкам.

например, вы можете увидеть это:

days = "1000101"; // fixed bug where days were incorrectly set to "1010001"
41
ответ дан 27 November 2019 в 06:56
поделиться

Не следует создавать нестандартные структуры данных для замены стандартной структуры данных (в данном случае встроенного перечисления DayOfWeek). Вместо этого расширьте существующую структуру. Это работает практически так же, как метод битовых флагов, о котором вы говорили.

namespace ExtensionMethods
{
    public static class Extensions
    {
        /*
         * Since this is marked const, the actual calculation part will happen at
         * compile time rather than at runtime.  This gives you some code clarity
         * without a performance penalty.
         */
        private const uint weekdayBitMask =
            1 << Monday 
            | 1 << Tuesday
            | 1 << Wednesday
            | 1 << Thursday
            | 1 << Friday;
        public static bool isWeekday(this DayOfWeek dayOfWeek)
        {
            return 1 << dayOfWeek & weekdayBitMask > 0;
        }
    }   
}

Теперь вы можете сделать следующее:

Thursday.isWeekday(); // true
Saturday.isWeekday(); // false
23
ответ дан 27 November 2019 в 06:56
поделиться

Создайте класс, в котором можно проводить несколько дней недели. Внутри класса вы можете представлять данные в любом случае, но я бы определенно выбрал перечисление флагов, а не строку. Вне класса вы просто используете значения перечисления, а фактическая логика инкапсулируется в классе.

Что-то вроде:

[Flags]
public enum Days {
   Monday = 1,
   Tuesday = 2,
   Wednesday = 4,
   Thursday = 8,
   Friday = 16,
   Saturday = 32,
   Sunday = 64,
   MondayToFriday = 31,
   All = 127,
   None = 0
}

public class Weekdays {

   private Days _days;

   public Weekdays(params Days[] daysInput) {
      _days = Days.None;
      foreach (Days d in daysInput) {
         _days |= d;
      }
   }

   public bool Contains(Days daysMask) {
      return (_days & daysMask) == daysMask;
   }

   public bool Contains(params Days[] daysMasks) {
      Days mask = Days.None;
      foreach (Days d in daysMasks) {
         mask |= d;
      }
      return (_days & mask) == mask;
   }

}

Пример использования:

Weekdays workdays = new Weekdays(Days.MondayToFriday);
if (workdays.Contains(Days.Monday, Days.Wednesday)) {
   ...
}
6
ответ дан 27 November 2019 в 06:56
поделиться

Вопрос должен заключаться в том, увидят ли когда-нибудь человеческие глаза это сохраненное значение. Если это так, очевидно, что важен несколько удобочитаемый формат (хотя в этом случае я бы привел аргумент в пользу чего-то еще большего, например, массива настоящих названий дней).

Однако, по крайней мере, во всех случаях. в приложениях, которые я когда-либо создавал, такие данные помещаются где-то в крошечное поле и никогда больше не отображаются, кроме как через код C # - что означает, что битовые флаги определенно самые простые - они наиболее удобочитаемы в коде . Ваши коллеги действительно хотят написать синтаксический анализатор строк, который отображает 0 и 1 в значения вместо использования , встроенного в и , использовавшегося более 40 лет идеи поразрядных операций?

1
ответ дан 27 November 2019 в 06:56
поделиться

Забавно, что оба этих метода абсолютно одинаковы ; только метод flags более очевиден.

Я лично выбрал бы флаги (хотя потенциально, в зависимости от вашей модели, было бы лучше просто сохранить список как List против того, кто его держит).

- Edit

И, чтобы прояснить, я думаю, производительность не обязательно должна учитывать то, что вы делаете. Так что выбирайте наиболее читаемый. (Что, ИМХО, и есть названные флаги).

0
ответ дан 27 November 2019 в 06:56
поделиться

Метод Flags идиоматичен (то есть это то, что делают опытные программисты и привыкли видеть и делать, по крайней мере, на языках C / C ++ / C #).

0
ответ дан 27 November 2019 в 06:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: