Introduction
I was assigned the task of creating an application that consumes a couple of RSS feeds to compile a concise list of recent news headlines from various sources and various categories, including top news headlines, sports, business, entertainment, politics, etc.
The final top level class is a ContentMonitor
that downloads new content at every specified interval. When an instance of a ContentMonitor
object is created, I wanted the user's of the class to be able to specify which feeds it should monitor and from which a master list of headlines should be compiled and exported to a local XML document.
After thinking a bit about it, I decided to create a NewsCategory
enumeration that implements the FlagsAttribute
so that the user of the class could pass any combination of news categories to the ContentMonitor
, which would then be responsible for retrieving those specified headlines.
The implementation of the monitor class isn't relative to this article, but I wanted to show how I went about using bitwise operations to pass a "list" of enum values into an object, and then to retrieve those values on the other side to determine which headlines were being requested.
Background
If you need to familiarize yourself with bitwise operations, check out this article. The official MSDN documentation on the FlagsAttibute
class can be found here. I won't go into any specific detail about how bitwise operations work. I assume that if you're reading this, you already know a thing or two.
Using the code
Enough chit chat. On to the code.
Here is the declaration of my NewsCategory
enumeration:
[FlagsAttribute]
public enum NewsCategory : int
{
TopHeadlines =1,
Sports=2,
Business=4,
Financial=8,
World=16,
Entertainment=32,
Technical=64,
Politics=128,
Health=256,
National=512
}
And, here is the property of the ContentMonitor
that sets the NewsCategory
member:
public NewsCategory ContentCategories
{
set
{
int[] arr = (int[])System.Enum.GetValues(typeof(NewsCategory));
int largest = GetLargestValue(arr);
int smallest = GetSmallestValue(arr);
for (int i = smallest; i <= largest; i = i * 2)
{
switch ((NewsCategory)(value & (NewsCategory)i))
{
case NewsCategory.Business: break;
case NewsCategory.Entertainment: break;
case NewsCategory.Financial: break;
case NewsCategory.Health: break;
case NewsCategory.National: break;
case NewsCategory.Politics: break;
case NewsCategory.Sports: break;
case NewsCategory.Technical: break;
case NewsCategory.TopHeadlines: break;
case NewsCategory.World: break;
default: break;
}
}
}
}
And finally, here is how the ContentMonitor
is "told" which news content to consume using a bitwise OR operation.
ContentMonitor mon = new ContentMonitor();
mon.ContentCategories = NewsCategory.Business |
NewsCategory.Entertainment |
NewsCategory.Politics;
So, let's break this apart.
The very first thing I wanted to do was retrieve the smallest and largest constant values of the NewsCategory
enumeration. Assume that the methods GetLargestValue()
and GetSmallestValue()
return the largest and smallest numbers in the array that's passed to the them, respectively.
Now, I set up a for
loop to iterate from the smallest enum value to the largest, in multiples of two. If the smallest enum constant were 1, and the largest were 512, at each iteration of the loop, i
would be 1, 2, 4, 8, 16, 32, 64, etc., all the way to 512. Note that by getting the smallest and largest constants dynamically, I don't have any numbers hard-coded in the for
loop. If I decided to add a new item to my enumeration and assign it the value of 1024 (512 * 2), I only have to update the enumeration declaration itself. This, way the loop still knows how many iterations to go through to cover all the enum values.
Now that we've passed a "list" of bitwise NewCategory
values to the ContentMonitor
, how do we know what ones we've got to deal with? This is where bitwise AND comes into play. One way of retrieving the values would be like this:
if ((value & NewsCategory.Politics) == NewsCategory.Politics) {...}
if ((value & NewsCategory.Business) == NewsCategory.Business) {...}
if ((value & NewsCategory.Financial) == NewsCategory.Financial) {...}
Mostly for readability, I didn't want to do a bunch of bitwise AND operations placed in a series of if
statements where I had to type the NewsCategory
twice in the same line. I always love it when I can make concise, easy to read modules of code. (Yes, I could have put the AND operation in a function, and just passed in the news category that way, but I didn't like that either.)
If you look at the switch
statement, it's doing basically the same thing as the series of if
statements above. It takes the current value of i
(which represents an enum constant value) and typecasts it to a NewsCategory
enum. Simple enough. After that, it uses the NewsCategory
value passed into the property, and performs a bitwise AND operation on it, which results in a NewsCategory
value that can be used in a switch
statement. It's basically like doing the following:
value = NewsCategory.Business | NewsCategory.Entertainment;
NewsCategory tmpCat = (NewsCategory)4;
NewsCategory newCat = (value & tmpCat);
if (newCat == NewsCategory.Business)
{
}
Now, just test your conditions in the body of the switch
. I may have spent way more time creating this and writing about it than was really necessary, but it helped me understand more about how to use bitwise operations to pass multiple values into a class, and extract them to perform specific actions for each value. Hopefully, this will work for you sometime along the way. Also, if you feel anything in this article is erroneous or false, please don't hesitate to tell me. I love feedback and learning new things.