Проблемы с FlagsAttribute Enum
Итак, я создаю клиент 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, я не нахожу ответа.
Пожалуйста, помогите мне:)
Ответы
Ответ 1
Определение операторов сдвига означает, что для 32-битных чисел используются только 5 наименее значимых битов и только первые 6 бит для 64-битного; что означает:
1 << 5
является идентичным до
1 << 37
(оба значения 32
)
Сделав это:
MsgrVersion9 = 1L << 32
вы делаете это 64-битным числом, поэтому работа с @leppie работает; в противном случае <<
считается first (и обратите внимание, что 1<<32
идентичен 1<<0
, т.е. 1
), а , затем полученный 1
преобразуется в long
; поэтому он еще 1
.
Из §14.8 в спецификации ECMA:
Для предопределенных операторов число битов сдвига вычисляется следующим образом:
- Когда тип x равен
int
или uint
, счетчик сдвига задается младшими пятью битами счета. Другими словами, подсчет сдвига вычисляется из count & 0x1F
. - Когда тип x равен
long
или ulong
, счетчик сдвига задается шестью битами младшего разряда. Другими словами, подсчет сдвига вычисляется из count & 0x3F
.
Если итоговое значение сдвига равно нулю, операторы сдвига просто возвращают значение x.
Операции сдвига никогда не вызывают переполнения и не дают одинаковых результатов в проверенном и непроверенном контексте
Ответ 2
Проблема может заключаться в арифметическом переполнении.
В частности:
MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
Я предлагаю вам сделать это:
MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,
Во избежание случайного переполнения.
Update:
Похоже, что меньшее число на "касается" 31 бит, а большее - "32".