Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FlagsAttribute Enum problems

So I'm building an MSNP (windows live messenger) client. And I've got this list of capabilities

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

full list here http://paste.pocoo.org/show/383240/

The server sends each users capabilities to the client as a long integer, which I take and cast it to UserCapabilities

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

This is fine, and with atleast one user (with a capability value of 1879474220), I can do

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

and this will output

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

But with another user, who has the capability value of (3055849760), when I do the same, I just get the same number outputted

3055849760

What I would like to be seeing is a list of capabilities, as it is with the other user.

I'm sure there is a very valid reason for this happening, but no matter how hard I try to phrase the question to Google, I am not finding an answer.

Please help me :)

like image 912
NoPyGod Avatar asked May 05 '11 07:05

NoPyGod


People also ask

What is a flagged enum?

A flagged enum can be used to efficiently send and store a collection of boolean values. In a flagged enum, each value of the enum is assigned to a bit value. These must be bit values because each combination possible will be unique.

What is the role of flag attribute in enum?

The [Flag] attribute is used when Enum represents a collection of multiple possible values rather than a single value. All the possible combination of values will come. The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value.

What is Flag in C sharp?

A Flags is an attribute that allows us to represent an enum as a collection of values ​​rather than a single value. So, let's see how we can implement the Flags attribute on enumeration: [Flags] public enum UserType.

What does the flags attribute do?

Enum Flags Attribute The idea of Enum Flags is to take an enumeration variable and allow it hold multiple values. It should be used whenever the enum represents a collection of flags, rather than representing a single value. Such enumeration collections are usually manipulated using bitwise operators.


2 Answers

The definition of the shift operators means that only the 5 least significant bits are used for 32-bit numbers and only the first 6 bits for 64-bit; meaning:

1 << 5

is identical to

1 << 37

(both are 32)

By making it:

MsgrVersion9 = 1L << 32

you make it a 64-bit number, which is why @leppie's fix works; otherwise the << is considered first (and note that 1<<32 is identical to 1<<0, i.e. 1), and then the resulting 1 is converted to a long; so it is still 1.

From §14.8 in the ECMA spec:

For the predefined operators, the number of bits to shift is computed as follows:

  • When the type of x is int or uint, the shift count is given by the low-order five bits of count. In other words, the shift count is computed from count & 0x1F.
  • When the type of x is long or ulong, the shift count is given by the low-order six bits of count. In other words, the shift count is computed from count & 0x3F.

If the resulting shift count is zero, the shift operators simply return the value of x.

Shift operations never cause overflows and produce the same results in checked and unchecked context

like image 103
Marc Gravell Avatar answered Oct 19 '22 00:10

Marc Gravell


The problem could be with arithmetic overflow.

Specifically at:

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

I suggest you make it:

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

To prevent accidental overflow.

Update:

Seems likely as the smaller number on 'touches' 31 bits, while the bigger one 'touches' 32 bits.

like image 23
leppie Avatar answered Oct 19 '22 00:10

leppie