4

In C#, I'm storing a flags enum value in a database as a byte. For example, for the following Flags enum:

[Flags]
public enum Options
{
    None = 0,
    First = 1,
    Second = 2,
    Third = 4
}

If I want to record 'First' and 'Second', I save this as a byte of '3' in the 'options' field of a record in the database.

So when using LINQ, how can I check if the value in the database matches 'any' of the options in an argument passed as an 'Options' enum, something like this pseudocode:

    public static Something(Options optionsToMatch)
    {
       db.MyEntity.Get(a => a.options contains any of the options in optionsToMatch);
Chris Halcrow
  • 21,541
  • 11
  • 115
  • 145

2 Answers2

1

Here's code that does what you want by iterating over the enums (I took that answer from here).

   static void Main()
    {
        //stand-in for my database
        var options = new byte[] { 1, 2, 3, 3, 2, 2, 3, 4, 2, 2, 1,5 };

        var input = (Options)5;

        //input broken down into a list of individual flags
        var optional = GetFlags(input).ToList();
        //get just the options that match either of the flags (but not the combo flags, see below)
        var foundOptions = options.Where(x => optional.Contains((Options)x)).ToList();
        //foundOptions will have 3 options: 1,4,1
    }

    static IEnumerable<Enum> GetFlags(Enum input)
    {
        foreach (Enum value in Enum.GetValues(input.GetType()))
            if (input.HasFlag(value))
                yield return value;
    }

EDIT

If you also want to find 5 in this example (the combo of options), just add an extra or condition like so:

var foundOptions = options.Where(x => optional.Contains((Options)x) || input == (Options)x).ToList();
Community
  • 1
  • 1
Kolichikov
  • 2,594
  • 24
  • 40
0

First, define the flags usefully. A single set bit for each flag, so that they can be easily combined in any combination.

[Flags]
enum opts : byte {
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    D = 1 << 3,
    //.. etc
}

Then just bitwise AND and see if it's not equal to 0

opts a = opts.A | opts.D;
opts b = opts.B | opts.C | opts.D;
var c = a & b; //D

if((byte)c!=0){
    // ... things
}
moreON
  • 1,787
  • 16
  • 18
  • First of all,he has already defined the flags "usefully", having done exactly what you have done. Convert your opts to byte and you'll notice that they are 1,2,4,8. The only thing your method adds is an extra mental check for all subsequent developers as to what 2^3 is. It also makes the code cumbersome, because if 'opts b' is a list from a database with a few hundred results, are you proposing that the code iterate and bitwise or all of them, just to compare them with another bitwise or? The whole point of Flags is that the bitwise or is already done for you. – Kolichikov Aug 25 '16 at 04:15
  • Huh, so they are, I think I misread a 3 in place of the 4. My bad. – moreON Aug 25 '16 at 04:18