Я часто вижу объявления перечисления флагов, в которых используются шестнадцатеричные значения. Например:
[Flags]
public enum MyEnum
{
None = 0x0,
Flag1 = 0x1,
Flag2 = 0x2,
Flag3 = 0x4,
Flag4 = 0x8,
Flag5 = 0x10
}
Когда я объявляю перечисление, я обычно объявляю его так:
[Flags]
public enum MyEnum
{
None = 0,
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8,
Flag5 = 16
}
Есть ли причина или объяснение, почему некоторые люди предпочитают записывать значение в шестнадцатеричном, а не в десятичном формате? На мой взгляд, проще запутаться при использовании шестнадцатеричных значений и случайно написать Flag5 = 0x16
вместо Flag5 = 0x10
.
c#
.net
enums
enum-flags
Ади Лестер
источник
источник
10
а не0x10
если вы будете использовать десятичные числа? В частности, потому что мы имеем дело с двоичными числами, а шестнадцатеричный тривиально можно преобразовать в / из двоичного?0x111
переводить в голове гораздо менее неприятно, чем273
...Flag1 | Flag2
3, а 3 не соответствует ни одному значению доменаMyEnum
.Ответы:
Обоснования могут быть разными, но я вижу преимущество в том, что шестнадцатеричное число напоминает вам: «Хорошо, мы больше не имеем дело с числами в произвольном изобретенном людьми мире десятичной системы. Мы имеем дело с битами - миром машин - и мы поиграем по ее правилам ". Шестнадцатеричный формат используется редко, если только вы не имеете дело с относительно низкоуровневыми темами, в которых структура памяти данных имеет значение. Его использование намекает на то, что мы сейчас в такой ситуации.
Кроме того, я не уверен насчет C #, но я знаю, что в C
x << y
- допустимая константа времени компиляции. Наиболее очевидным кажется использование битовых сдвигов:источник
x << y
обозначениями.1 << 10 = KB
,1 << 20 = MB
,1 << 30 = GB
И так далее. Это действительно хорошо, если вы хотите создать массив размером 16 КБ для буфера, вы можете просто пойти,var buffer = new byte[16 << 10];
Это позволяет легко увидеть, что это бинарные флаги.
Хотя прогрессия делает это еще яснее:
источник
012
есть на самом деле10
.int
вместо этого. Я знаю, что это глупо ... но от привычек трудно избавиться.Я думаю, это просто потому, что последовательность всегда 1, 2, 4, 8, а затем добавляется 0.
Как видите:
и так далее, если вы помните последовательность 1-2-4-8, вы можете построить все последующие флаги, не запоминая степени двойки.
источник
Потому
[Flags]
что означает, что перечисление действительно является битовым полем . С[Flags]
вы можете использовать побитовое И (&
) и OR (|
) операторы , чтобы объединить флаги. При работе с такими двоичными значениями почти всегда проще использовать шестнадцатеричные значения. Именно по этой причине мы в первую очередь используем шестнадцатеричные числа. Каждому шестнадцатеричному символу соответствует ровно один полубайт (четыре бита). С десятичным числом это преобразование 1 в 4 не выполняется.источник
Потому что существует механический и простой способ удвоить степень двойки в шестнадцатеричной системе. В десятичном выражении это сложно. Это требует длительного умножения в голове. В шестнадцатеричном формате это простое изменение. Вы можете выполнять это полностью,
1UL << 63
но не можете использовать десятичные дроби.источник
Потому что людям легче следить за тем, где биты находятся во флаге. Каждая шестнадцатеричная цифра может соответствовать 4-битной двоичной системе.
Обычно вы хотите, чтобы ваши флаги не перекрывали биты, самый простой способ сделать и визуализировать это - использовать шестнадцатеричные значения для объявления ваших флагов.
Итак, если вам нужны 16-битные флаги, вы будете использовать 4-значные шестнадцатеричные значения, и таким образом вы сможете избежать ошибочных значений:
источник