1

I have a method which takes an enum flags parameter of items to display. Items in the database can have multiple flags set, and the value passed to the method can also have multiple flags set. Eg:

Item1 = Flag1
Item2 = Flag1 | Flag3
Item3 = Flag2 | Flag3

I want to be able to pass these values to the method and have the corresponding items returned.

  • If I pass Flag2 | Flag3, return Item2 and Item3 (Because each flag matches one of the flags set in the entity)
  • If I pass Flag1, return Item1 and Item2

...etc. I've been experimenting with .Where and .Any and I still have absolutely no clue how to do this, if it's even possible. I'm targetting .NET 4.5 and using EF5.

Echilon
  • 10,064
  • 33
  • 131
  • 217

4 Answers4

2

Use the bitwise And operator

MyFlags value = MyFlags.Flag2 | MyFlags.Flag3;

MyFlags item1 = MyFlags.Flag1;
MyFlags item2 = MyFlags.Flag1 | MyFlags.Flag3;
MyFlags item3 = MyFlags.Flag2 | MyFlags.Flag3;

bool matchItem1 = (value & item1) > 0; //false
bool matchItem2 = (value & item2) > 0; //true
bool matchItem3 = (value & item3) > 0; //true

[Flags]
enum MyFlags
{
    Flag1 = 1,
    Flag2 = 2,
    Flag3 = 4
}
Bas
  • 26,772
  • 8
  • 53
  • 86
1

Given a list of MyItems, each of which has a property Flags of type MyFlags:

public IEnumerable<MyItem> GetItemsWithFlag(IList<MyItem> items, MyFlags flags) {
    var flagsL = Convert.ToUInt64(flags);

    foreach (var value in Enum.GetValues(typeof(MyFlags))) {
        var valueL = Convert.ToUInt64(value);

        if ((flagsL & valueL) == valueL) {
            foreach (var item in items) {
                var itemL = Convert.ToUInt64(item.Flags);

                if ((itemL & valueL) == valueL) {
                    yield return item;
                }
            }
        }
    }
}

This will loop through all possible flags and, if the flag is set in the parameter flags, return all items with that flag set in the Flags property

Brian Kintz
  • 1,983
  • 15
  • 19
0

I believe it is possible. Your Enum must have the [Flags] attribute set, and then it is as simple as .Where(p=>p.Flags == FilterFlags)

Read more about Enum flags here

Community
  • 1
  • 1
Tsabo
  • 834
  • 4
  • 9
  • But that will only show me items which exactly match. I want to show items where any of the flags set on the item match any of the flags given as a parameter. With your method, If I pass Flag1 | Flag3, only Item2 will be returned (Not Item1), which isn't what I want. – Echilon Jul 31 '13 at 12:26
  • That is because you want the use the & operator in your flag operations, and not | – Tsabo Jul 31 '13 at 12:39
0

I was looking at this the wrong way. For me, flags was more of a FlagsToExclude. Eg:

[Flags]
public enum ForumTopicFlags : int
{
    None = 0,
    Sticky = 1,
    Spam = 2,
    Deleted = 4
}

The default flag is 0. For moderators, I need to pass null as the parameter, which is ignored by the DAL and eveything is returned. For standard users, I can pass Spam | Deleted, which is excluded by comparing it like this:

var filteredFlags = dbContext.Topics.Where(i => (i.Flags & flagsToExclude <= 0);
Echilon
  • 10,064
  • 33
  • 131
  • 217