0

I have a C#/.NET 4.0 application that receives and parses some data from a network connection. One particular piece of data that I need to parse is a UInt16 value that represents a set of flags. I've defined an enum that represents these flags like this:

public enum Fields
{
    None = 0,
    FirstFlag = 1,
    SecondFlag = 2,
    ThirdFlag = 4,
    FourthFlag = 8,
    FifthFlag = 16,
    SixthFlag = 32,
    SeventhFlag = 64,
    EighthFlag = 128
}

I going to try to use bitwise operators on this UInt16 value to determine which flags it indicated had been set. But then I ran across Enum.HasFlag() method and at first glance, that seemed like it would be easier than bitwise operations. I've been trying to use the following method to determine which flags are set in the UInt16 value:

public static void CheckForSetFields(Fields value)
{
    if (value.HasFlag(Fields.None))
    {
        System.Diagnostics.Debug.WriteLine("No fields are set!");
    }
    else
    {
        if (value.HasFlag(Fields.FirstFlag))
        {
            System.Diagnostics.Debug.WriteLine("First flag is set.");
        }
        if (value.HasFlag(Fields.SecondFlag))
        {
            System.Diagnostics.Debug.WriteLine("Second flag is set.");
        }

        // etc., etc.

        if (value.HasFlag(Fields.EighthFlag))
        {
            System.Diagnostics.Debug.WriteLine("Eighth flag is set.");
        }
    }
}

This method obviously takes a parameter of type Fields (my enum) but I'm working with a UInt16 value that was sent to me. I assume that I need to convert the UInt16 into an instance of the Fields enum but I'm not sure how to do that. It doesn't seem to be as simple as just casting it (which doesn't give me an error but also doesn't return the expected results, either). Is it possible to do this using Enum.HasFlag() or should I just implement the bitwise operations and be done with it?

bmt22033
  • 6,880
  • 14
  • 69
  • 98

3 Answers3

3

I assume that I need to convert the UInt16 into an instance of the Fields enum but I'm not sure how to do that.

That's easy - you need to cast to the underlying type of the enum, and then you can cast to the enum itself:

Fields value = (Fields) (int) incomingValue;

EDIT: As noted in comments, this check doesn't do what you want it to:

if (value.HasFlag(Fields.None))

From the documentation:

If the underlying value of flag is zero, the method returns true.

Basically you want:

if (value == 0)

for that test instead.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon. I was looking for a quick way to test all possible combinations of flag values so I tried this inside of a for loop with incomingValue being 0 to Int16.MaxValue. Every iteration of the loop calls CheckForSetFields(value) which always results in "No fields are set!" being written to the debug output. Shouldn't there be some flag combinations where if (value.HasFlag(Fields.None)) is false? Hope that makes sense. Thanks again for the reply. – bmt22033 Sep 04 '14 at 19:10
  • @user685869: Basically `HasFlag(Fields.None)` is incorrect - I'll edit my answer to explain. – Jon Skeet Sep 04 '14 at 20:26
  • Thanks for the additional explanation, Jon! – bmt22033 Sep 05 '14 at 10:59
1

Maybe you want a Enum with UInt16 type?

Declare your Enum using enum SomeFlag : UInt16 { } then casting your value to the enum directly, using (SomeFlag)someValue, will work.

And it's a good practice to add [Flags] attribute to your flag enum. It doesn't really do something, but you can tell yourself and other viewers it's a flag, and debugger will show combined flags instead numeric value in watch panel.

yume_chan
  • 858
  • 9
  • 22
0

The problem is that in your first if, you are comparing your value to 0. HasFlag uses bitwise and of value and the passed enum and result of bitwise and of any value and 0 is 0. So you won't get to other conditions.

brz
  • 5,926
  • 1
  • 18
  • 18