Using enum flags to write filters in Linq

Here’s the premise. Suppose we have a cookbook that contains all possible recipes with their names and needed ingredients. Using Linq it should be easy to query the cookbook and, for example, only show those recipes you can make given one or more ingredients you have at your house. My solution is a) extremely nice or b) very strange, bloated and way wrong. I leave it up to you and make sure to message me if you have a much nicer solution…because franky, I’m not a big fan of what follows (I have the itching sensation that using the correct binary logic I can solve this problem much easier…).

Using a bitflag enumeration

In the old MFC days you couldn’t get around using bitflags every 2 lines or code, or so it seemed. To solve this problem, we are again using enumeration that can act as bitflags: meaning you can add 2 or more items together in one variable and still identify the singular items. What you need for this is an enumeration with the [Flags] attribute, which basically sas that this enumeration can be used as a bit field (i.e. a set of flags).A very nice tutorial on bitflags can be found here: http://www.abhisheksur.com/2010/10/make-your-enumeration-to-bit-flags.html .

Making LINQ queries on the cookbook

There are three possible sorts of queries we now would like to do on our cookbook:

Show all recipes of which at least one chosen ingredient is present

Show only recipes that only contain given ingredients

Show all recipes that at least contain all chosen ingredients.

Suppose we define the following filter that we use to show the previous three types of queries:

IngredientsEnum filterIngredients =

IngredientsEnum.Chicken | IngredientsEnum.Spinach;

At least one query

To show all recipes that contains at least one of the ingredients in the filter, we need to perform a ‘bitwise and’ each recipe with the filter. If this addition returns a value larger than 0, we know that at least one ingredient is present.

The following query will thus return all recipes in the cookbook except for the “Raw tomato”:

Only given ingredients query

If we only would like to know what recipe only contains those ingredients of our filter, we have the following query (which will only return “Mario’s Lovely Pizza”):

var possiblities =

from c in CookBookwhere c.Ingredients == filterIngredientsselect c;

This is the reason why each ingredient in our enumeration should be powers of 2. If we simply incremented each enumitem with 1, the previous query could return other recipes of which the bitwise and of the ingredients by ‘chance’ gives a value equal to that of filter.

At least query

To show all recipes that contain all the ingriedients in the filter, but also those that contain more than those alone, we can use the HasFlag() method. The following query, applied to our Chick with Spinach filter will thus return both “Mario’s Lovely Pizza” and “Tim’s secret dish”:

var possiblities =

from c in CookBookwhere c.Ingredients.HasFlag(filterIngredients)select c;

Seems useful, but you have to be aware of the limitations of Enums: they can’t be easily extended without changing the source code and flag enums only support a limited number of values, because of their bitwise nature. I wouldn’t use them to represent ingredients, for example, because future recipes may need to extend the existing collection of available ingredients.