FlagsAttribute Enum проблемы - PullRequest
31 голосов
/ 05 мая 2011

Итак, я создаю клиент MSNP (Windows Live Messenger). И у меня есть этот список возможностей

public enum UserCapabilities : long
{
    None = 0,
    MobileOnline = 1 << 0,
    MSN8User = 1 << 1,
    RendersGif = 1 << 2,
    ....
    MsgrVersion7 = 1 << 30,
    MsgrVersion8 = 1 << 31,
    MsgrVersion9 = 1 << 32,
}

полный список здесь http://paste.pocoo.org/show/383240/

Сервер отправляет каждому пользователю возможности клиента как длинное целое число, которое я беру и преобразую в UserCapabilities

capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;

Это нормально, и, по крайней мере, с одним пользователем (со значением способности 1879474220) я могу сделать

Debug.WriteLine(_msgr.GetUser(usr).Capabilities);

и это выдаст

RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7

Но с другим пользователем, у которого есть значение способности (3055849760), когда я делаю то же самое, я просто получаю то же число, которое выводится

3055849760

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

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

Пожалуйста, помогите мне:)

Ответы [ 2 ]

32 голосов
/ 05 мая 2011

Определение операторов сдвига означает, что только 5 младших разрядов используются для 32-разрядных чисел и только первые 6 разрядов для 64-разрядных; что означает:

1 << 5

идентично

1 << 37

(оба 32)

Сделав это:

MsgrVersion9 = 1L << 32

вы делаете его 64-битным числом, поэтому исправление @ leppie работает; в противном случае << считается первым (и обратите внимание, что 1<<32 идентичен 1<<0, то есть 1 ) и , затем , в результате 1 преобразуется в long; так что все еще 1.

Начиная с §14.8 в спецификации ECMA:

Для предопределенных операторов число сдвигаемых битов вычисляется следующим образом:

  • Когда тип x равен int или uint, счет сдвига задается младшими пятью битами count . Другими словами, число сдвигов вычисляется из count & 0x1F.
  • Когда тип x равен long или ulong, счет сдвига задается младшими шестью битами count . Другими словами, число сдвигов вычисляется из count & 0x3F.

Если полученный счетчик сдвига равен нулю, операторы сдвига просто возвращают значение x.

Операции сдвига никогда не вызывают переполнения и дают одинаковые результаты в проверенном и непроверенном контексте

10 голосов
/ 05 мая 2011

Проблема может быть в арифметическом переполнении.

В частности:

MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,

Я предлагаю вам сделать это:

MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,

Для предотвращения случайного переполнения.

Обновление:

Вероятно, что меньшее число при касании 31 бит, в то время как большее число касается 32 бит.

...