【问题标题】:FlagsAttribute Enum problemsFlagsAttribute 枚举问题
【发布时间】:2011-05-05 07:08:33
【问题描述】:

所以我正在构建一个 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 提出了一个很好的问题!

标签: c# .net enum-flags


【解决方案1】:

移位运算符的定义是指32位数字只使用最低5位,64位只使用前6位;意思:

1 << 5

相同
1 << 37

(都是32

通过制作:

MsgrVersion9 = 1L << 32

您将其设为 64 位数字,这就是 @leppie 的修复有效的原因;否则&lt;&lt; 被视为first(注意1&lt;&lt;32 1&lt;&lt;0 相同,即1),然后将生成的1 转换为long;所以它仍然是1

来自 ECMA 规范中的 §14.8:

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

  • x的类型为intuint时,移位计数由count的低五位给出。换句话说,移位计数是根据count &amp; 0x1F 计算的。
  • x的类型为longulong时,移位计数由count的低六位给出。换句话说,班次计数是根据count &amp; 0x3F 计算得出的。

如果结果移位计数为零,则移位运算符只返回 x 的值。

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

【讨论】:

  • 它可能不叫'溢出'但效果是一样的,即(1L &lt;&lt; 33) &amp; 0xffffffff。我认为规范文本暗示在移位时永远不会引发溢出异常。
  • @leppie - 但如果只是为了避免溢出,那么你应该期望(对于int)任何&lt;&lt;32 都为零;与将其 &lt;&lt;16 移动两次(并非如此)相同。
【解决方案2】:

问题可能与算术溢出有关。

具体在:

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

我建议你做到:

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

为了防止意外溢出。

更新:

似乎较小的数字“触及”31 位,而较大的数字“触及”32 位。

【讨论】:

  • 原因很简单:1是Int32,31也是Int32,结果又是Int32,是一个有符号的int,最大值是2,147,483,647,但是1
  • @Daniel @NoPyGod 这与溢出无关;看我的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多