FlagsAttribute Enum问题

NoP*_*God 31 .net c# enum-flags

所以我正在构建一个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,
}
Run Code Online (Sandbox Code Playgroud)

完整列表http://paste.pocoo.org/show/383240/

服务器将每个用户的功能作为一个长整数发送给客户端,我将其转换为UserCapabilities

capabilities = Int64.Parse(e.Command.Args[3]);
user._capabilities = (UserCapabilities)capabilities;
Run Code Online (Sandbox Code Playgroud)

这很好,至少有一个用户(能力值为1879474220),我能做到

Debug.WriteLine(_msgr.GetUser(usr).Capabilities);
Run Code Online (Sandbox Code Playgroud)

这将输出

RendersGif, RendersIsf, SupportsChunking, IsBot, SupportsSChannel, SupportsSipInvite, MsgrVersion5, MsgrVersion6, MsgrVersion7
Run Code Online (Sandbox Code Playgroud)

但是对于具有(3055849760)能力值的另一个用户,当我这样做时,我只输出相同的数字

3055849760
Run Code Online (Sandbox Code Playgroud)

我希望看到的是功能列表,与其他用户一样.

我确信这种情况有一个非常合理的原因,但无论我多么努力地向谷歌提问,我都找不到答案.

请帮我 :)

Mar*_*ell 32

移位运算符的定义意味着只有5个最低有效位用于32位数,而前6位用于64位; 含义:

1 << 5
Run Code Online (Sandbox Code Playgroud)

完全相同

1 << 37
Run Code Online (Sandbox Code Playgroud)

(都是32)

通过制作:

MsgrVersion9 = 1L << 32
Run Code Online (Sandbox Code Playgroud)

你把它变成64位数,这就是为什么@ leppie的修复工作; 否则<<被认为是第一(请注意,1<<32 是相同的 1<<0,即,1),和然后将所得1被转换成long; 所以它仍然是1.

从ECMA规范中的§14.8开始:

对于预定义的运算符,要移位的位数计算如下:

  • 当的类型Xintuint,移位计数由低阶的5位给出计数.换句话说,移位计数是从count & 0x1F.
  • x的类型是long或时ulong,移位计数由低位6位计数给出.换句话说,移位计数是从count & 0x3F.

如果得到的移位计数为零,则移位运算符只返回x的值.

Shift操作永远不会导致溢出,并在已检查和未检查的上下文中产生相同的结果

  • @leppie - 但如果它只是避免溢出,那么你应该期望(对于`int`)任何`<< 32`将为零; 就像两次移动它"<< 16"一样(事实并非如此). (3认同)

lep*_*pie 10

问题可能是算术溢出.

具体在:

MsgrVersion8 = 1 << 31,
MsgrVersion9 = 1 << 32,
Run Code Online (Sandbox Code Playgroud)

我建议你做到:

MsgrVersion8 = 1L << 31,
MsgrVersion9 = 1L << 32,
Run Code Online (Sandbox Code Playgroud)

防止意外溢出.

更新:

似乎可能是'触摸'31位上的较小数字,而较大的'触摸'32位.

  • 原因很简单:1是`Int32`,31也是`Int32`,结果又是`Int32`,这是一个有符号的int,最大值为2,147,483,647,但是1 << 31是2,147,483,648,所以它将溢出到-2,147,483,648. (4认同)
  • @Daniel @NoPyGod这与溢出无关; 看到我的回答 (4认同)