Почему использование flags+bitmasks, а не серия булевских переменных?

Существует раздел приблизительно пиксельное управление в документации W3C.

Вот пример о том, как инвертировать изображение :

var context = document.getElementById('myCanvas').getContext('2d');

// Get the CanvasPixelArray from the given coordinates and dimensions.
var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

// Loop over each pixel and invert the color.
for (var i = 0, n = pix.length; i < n; i += 4) {
    pix[i  ] = 255 - pix[i  ]; // red
    pix[i+1] = 255 - pix[i+1]; // green
    pix[i+2] = 255 - pix[i+2]; // blue
    // i+3 is alpha (the fourth element)
}

// Draw the ImageData at the given (x,y) coordinates.
context.putImageData(imgd, x, y);

24
задан Winston Fassett 10 September 2009 в 17:12
поделиться

10 ответов

Традиционно это был способ уменьшить использование памяти. Так что да, в C # он довольно устарел: -)

Как метод программирования, он может быть устаревшим в сегодняшних системах, и вы вполне можете использовать массив bool, но ...

Это быстро сравнивает значения, хранящиеся в виде битовой маски. Используйте логические операторы И и ИЛИ и сравните полученные 2 целых числа.

Он использует значительно меньше памяти. Помещение всех 4 значений вашего примера в битовую маску потребует полбайта. При использовании массива bool, скорее всего, для объекта массива будет использовано несколько байтов плюс длинное слово для каждого bool. Если вам нужно сохранить миллион значений, вы точно поймете, почему версия с битовой маской лучше.

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

И из-за структуры памяти намного быстрее во всех аспектах, чем массив. Это почти так же быстро, как при использовании одного 32-битного целого числа. Все мы знаем, что это настолько быстро, насколько это возможно для операций с данными.

18
ответ дан 28 November 2019 в 22:59
поделиться
  • Простая установка нескольких флагов в любом порядке.

  • Легко сохранить и получить в базу данных серию 0101011.

12
ответ дан 28 November 2019 в 22:59
поделиться

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

7
ответ дан 28 November 2019 в 22:59
поделиться

Это также может сделать методы более понятными. Представьте себе метод с 10 булевыми значениями и 1 битовой маской.

6
ответ дан 28 November 2019 в 22:59
поделиться

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

Но даже тогда я не думаю, что это настоящая причина. Причина, по которой я предпочитаю их, заключается в том, что C # дает мне возможность обрабатывать эти перечисления. Я могу добавить несколько значений с помощью одного выражения. Я тоже могу их удалить. Я даже могу сравнить сразу несколько значений с одним выражением с помощью перечисления. С логическими значениями код может стать, скажем, более подробным.

3
ответ дан 28 November 2019 в 22:59
поделиться

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

Наличие нескольких логических свойств упрощает чтение и понимание кода, изменение значений и предоставление комментариев Intellisense, не говоря уже о снижении вероятности ошибок. При необходимости вы всегда можете использовать поле флага перечисления внутри, просто убедитесь, что вы предоставляете установку / получение значений с помощью логических свойств.

3
ответ дан 28 November 2019 в 22:59
поделиться

У Раймонда Чена есть сообщение в блоге на эту тему .

Конечно, битовые поля экономят память данных, но вы должны уравновесить это с стоимость кода, возможность отладки и уменьшенная многопоточность.

Как говорили другие, его время в значительной степени прошло. Заманчиво продолжать это делать, потому что возиться с битами - это весело и круто, но это уже не более эффективно, у него есть серьезные недостатки с точки зрения обслуживания, он плохо работает с базами данных, и если вы не работаете в встроенный мир, у вас достаточно памяти.

3
ответ дан 28 November 2019 в 22:59
поделиться

С точки зрения модели домена, он просто лучше моделирует реальность в некоторых ситуациях. Если у вас есть три логических значения, таких как AccountIsInDefault и IsPreferredCustomer и RequiresSalesTaxState, то нет смысла добавлять их в одно оформленное перечисление Flags, поскольку они не являются тремя разными значениями для одного и того же элемента модели домена.

Но если у вас есть набор логических значений, например:

 [Flags] enum AccountStatus {AccountIsInDefault=1, 
         AccountOverdue=2 and AccountFrozen=4}

или

  [Flags] enum CargoState {ExceedsWeightLimit=1,  
         ContainsDangerousCargo=2, IsFlammableCargo=4, 
         ContainsRadioactive=8}

Тогда полезно иметь возможность сохранить общее состояние Аккаунта (или груза) в ОДНОЙ переменной ...

2
ответ дан 28 November 2019 в 22:59
поделиться
  1. Эффективность использования пространства - 1 бит
  2. Эффективность использования времени - сравнение битов выполняется быстро с помощью оборудования.
  3. Независимость от языка - где данные могут обрабатываться с помощью числа Из разных программ вам не нужно беспокоиться о реализации логических значений на разных языках / платформах.

В большинстве случаев это не стоит компромисса с точки зрения обслуживания. Однако бывают случаи, когда это полезно:

  1. Сетевые протоколы - будет большая экономия в уменьшенном размере сообщений
  2. Устаревшее программное обеспечение - как только мне пришлось добавить некоторую информацию для трассировки в какое-то устаревшее программное обеспечение. Стоимость размещения информации в 2 байта заголовка, которые не использовались: 0.

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

1
ответ дан 28 November 2019 в 22:59
поделиться

Это для скорости и эффективности. По сути, все, с чем вы работаете, - это один тип int.

if ((flags & AnchorStyles.Top) == AnchorStyles.Top)
{
    //Do stuff
} 
0
ответ дан 28 November 2019 в 22:59
поделиться
Другие вопросы по тегам:

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