Bitmask type to perform binary operations

Posted on

Problem

Without any specific implementation details, how would you create a bitmask type that wraps binary arithmetic into something easy to read? Ideally, this would be used with an enum, which is why there are some generic methods.

Some Questions

  1. Is the type a struct or class?
  2. Is the type generic or are certain methods generic?
  3. Is it okay to constrain the generics to struct, IConvertible?
  4. Is a type like this preferred when working with bitmasks?

Starting Example: Here’s a fiddle.

//Example Use
var days = new Bitmask((ulong)(Day.Monday | Day.Tuesday));
days.Contains((ulong)Day.Friday); //false
days.Contains((ulong)Day.Monday); //true
//Example Use END    

public enum Day { Monday = 1, Tuesday = 2, Wednesday = 4, Thursday = 8, Friday = 16, Saturday = 32, Sunday = 64 }

public struct Bitmask
{
    //Bitmask Value
    private ulong _value;
    public ulong Value 
    { 
        get { return _value; }
        set { _value = value; }
    }   

    //Constructor
    public Bitmask(ulong value) { _value = value; }


    //Methods
    public bool Any() { return _value != 0; }

    public void Clear() { _value = 0; }

    public bool Contains(ulong value) { return (_value & value) == value; } 

    public bool Equals(ulong value) { return _value == value; }

    public List<TEnum> ToList<TEnum>() where TEnum : struct, IConvertible
    {
        var local = this;
        var result = ((TEnum[])Enum.GetValues(typeof(TEnum))).Where(m => local.Contains<TEnum>(m)).ToList();
        return result;  
    }   
}

Solution

It looks like you are misusing an enum as just a more cumbersome way to write a ulong.

If the days of the week are meant to be treated as a set rather than a single value (i.e., more like checkboxes than radio buttons), then you should be using the [Flags] attribute. In fact, this is almost exactly the example given in the MSDN documentation:

[Flags]
enum Days2
{
    None = 0x0,
    Sunday = 0x1,
    Monday = 0x2,
    Tuesday = 0x4,
    Wednesday = 0x8,
    Thursday = 0x10,
    Friday = 0x20,
    Saturday = 0x40
}

class MyClass
{
    Days2 meetingDays = Days2.Tuesday | Days2.Thursday;
}

Personally, I’d write the constants using left-shift operators:

[Flags]
enum Days2
{
    None = 0,
    Sunday = 1 << 0,
    Monday = 1 << 1,
    Tuesday = 1 << 2,
    Wednesday = 1 << 3,
    Thursday = 1 << 4,
    Friday = 1 << 5,
    Saturday = 1 << 6
}

Leave a Reply

Your email address will not be published. Required fields are marked *