2013-07-26 2 views
39

Я смотрел на коде, который я в настоящее время в моем проекте, и нашел что-то вроде этого:Зачем кому-то использовать оператор << в объявлении перечисления?

public enum MyEnum 
{ 
    open  = 1 << 00, 
    close = 1 << 01, 
    Maybe = 1 << 02, 
    ........ 
} 

<< операнда является сдвиг операнда, который сдвигает первый операнд влево на число бит, указанных во втором операнде ,

Но зачем кому-то использовать это в объявлении enum?

+21

Я не знаю, кто голосует, чтобы закрыть это, но это не вопрос «в первую очередь на основе мнения». Это технический вопрос, в котором конкретно задается вопрос о том, в чем смысл «<<» в этом сценарии. –

+0

@GrantWinney (не мои близкие голоса), но я вижу, как это «основано на мнениях», потому что вопрос в основном «почему кто-то использует« 1 << 2 », когда' 0x04' более читаем * для меня * ». –

+7

Я никогда не говорил, что 0x04 более читабельна, и я не сравнил оба. Цель вопроса состоит в том, чтобы понять побочные эффекты этого утверждения (= возможность комбинировать флаги) – JSBach

ответ

40

Это позволяет сделать что-то вроде этого:

var myEnumValue = MyEnum.open | MyEnum.close; 

без необходимости рассчитывать битовые значения кратные 2.

(как это):

public enum MyEnum 
{ 
    open  = 1, 
    close = 2, 
    Maybe = 4, 
    ........ 
} 
+1

** Примечание **: ['<<' декларация даст вам максимум до 64 различных состояний (на большинстве платформ). Если вам нужны более возможные состояния, это решение не будет работать] (http://stackoverflow.com/questions/8956364/app-states-with-bool-flags?answertab=votes#8956606) –

+2

Какое альтернативное решение даст больше, чем 64 ортогональных состояния? – Useless

+2

@GrijeshChauhan Большинство платформ? Это C#, поэтому размер целочисленных типов не зависит от платформы. Тип левого операнда оператора '<<' определяет, какую перегрузку использовать. Например, с 's' целое число,' 1 << s' дает 32-битный 'int',' 1u << s' дает 32-разрядный неподписанный 'uint',' 1L << s' дает 64-битный 'long',' 1ul << s' '' ulong' и '(BigInteger) 1 << s' или' BigInteger.One << s' дает целочисленный произвольный размер (требуется ссылка на 'System.Numerics.dll 'сборка '. –

22

Это обычно используются с битовыми полями, так как ясно, что картина, устраняет необходимость вручную вычислить правильные значения и, следовательно, уменьшает вероятность ошибок

[Flags] 
public enum SomeBitField 
{ 
    open = 1 << 0 //1 
    closed = 1 << 1 //2 
    maybe = 1 << 2 //4 
    other = 1 << 3 //8 
    ... 
} 
+1

@ RichardDeeming - Вы правы, конечно, спасибо. – Lee

+0

Я думаю, вы имеете в виду побитовые операции, а не битовые поля. Битвые поля, по крайней мере в C-мире, являются подчиненными элементами структуры. – noamtm

6

Это просто означало быть чисты/более интуитивно понятный способ записи бит. 1, 2, 3 является более понятной для человека последовательностью, чем 0x1, 0x2, 0x4 и т. Д.

10

Чтобы не вводить значения для перечисления Flags вручную.

public enum MyEnum 
{ 
    open  = 0x01, 
    close = 0x02, 
    Maybe = 0x04, 
    ........ 
} 
+5

+1. Вероятно, '' Флаги '' на такой 'enum' прояснить использование ... но не все заботятся. –

6

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

Что это фактически означает это:

public enum MyEnum 
{ 
    open = 1; 
    close = 2; 
    Maybe = 4; 
    //... 
} 

Это просто более пуленепробиваемым метод создания [Flags] ENUM.

6

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

Короткая версия:

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

Так что я мог позвонить вам по телефону и сказать: «Эй, какой бит для открытия файла ?» И вы бы сказали: «Бит 0». И я бы написал в своем коде open = 1 << 0. Поскольку номер справа от << указывает номер бит.

.

Длинная версия:

Традиционно биты в слове нумеруются справа налево, начиная с нуля. Таким образом, младший бит - бит номер 0, и вы подсчитываете, как вы идете к наиболее значимый бит. Есть несколько benefits для маркировки битов этого способа .

Одним из преимуществ является то, что вы можете говорить о одном и том же бите независимо от размера слова. Например, я мог бы сказать, что как в 32-битном слове 0x384A, так и в 8-битовом слове 0x63 устанавливаются биты 6 и 1. Если вы пронумеровали свои биты в другом направлении, вы не смогли бы сделать это .

Еще одно преимущество заключается в том, что значение бита просто увеличивается до уровня бит . Например, двоичный код 0101 имеет биты 2 и 0. Бит 2 вносит значение 4 (2^2) в число, а бит 0 вносит значение 1 (2^0). Таким образом, значение , конечно, 4 + 1 = 5.

Это длинное объяснение фона приводит нас к сути: нотация << сообщает вам номер бит, просто взглянув на него.

номер 1 сам по себе в операторе 1 << n просто один бит установлен в позиции бита 0. Когда вы перемещаетесь, что число уехавших, вы затем двигаться, что установить бит в другую позицию в количестве. Удобно, сумма, которую вы сдвигаете , сообщает вам номер бит, который будет установлен.

1 << 5: This means bit 5. The value is 0x20. 
1 << 12: This means bit 12. The value is 0x40000. 
1 << 17: This means bit 17. The value is 0x1000000. 
1 << 54: This means bit 54. The value is 0x40000000000000. 
      (You can probably see that this notation might be helpful if 
      you're defining bits in a 64-bit number) 

Эта запись действительно очень удобно, когда вы взаимодействуете с другим компонентом, как отображения битов в слове на аппаратный регистр. Как и вы, у есть устройство, которое включается при записи в бит 7. Таким образом, инженер-инженер напишет лист данных, в котором говорится, что бит 7 позволяет устройству. И вы должны написать в свой код ENABLE = 1 << 7. Легко.

О стрелять. Инженер просто отправил ошибочную информацию в техническое описание, в котором говорилось, что это , предположительно, бит 15, а не бит 7. Это нормально, просто измените код на .

Что делать, если ENABLE были на самом деле, когда оба бита 7 и 1 были установлены одновременно?

ENABLE = (1 << 7) | (1 << 1).

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

0

Он равен силам двух.

public enum SomeEnum 
{ 
    Enum1 = 1 << 0, //1 
    Enum2 = 1 << 1, //2 
    Enum3 = 1 << 2, //4 
    Enum4 = 1 << 3  //8 
} 

И с таким перечислением вы будете иметь функцию, которая выглядит следующим образом:

void foo(unsigned ind flags) 
{ 
    for (int = 0; i < MAX_NUMS; i++) 
     if (1 << i & flags) 
     { 
      //do some stuff... 
      //parameter to that stuff probably is i either enum value 
     } 
} 

и призови к этой функции будет foo(Enum2 | Enum3); и он будет делать что-то со всеми заданными значениями перечислений.

Смежные вопросы