Using Flags Instead of Arrays of Enum


This is a short post based on a problem I had today where I have to either loop through an array of enum multiple times to ensure proper ordering or actually tear the array apart. The problem, however, is very common.

Here is the issue, so you understand the context of this article. I have a service method that requires an array of a particular enum. The call is something like this:

var client = new ServiceClient();
var request = new TreeRequest( { more here} );
var purposesArray = { PurposeEnum.Systems, PurposeEnum.Accessories };
var response = client.GetTree(request, purposesArray);

This seems fine, if you examine it directly, as I can iterate through the enum values and run the service to product the hierarchy needed. But, there are two issues.

  1. The enum values must run in a certain order, as the root of the tree comes out of a particular value
  2. The current service call accepts multiple values, but only runs the first one

The second item above is not problematic from the enumeration array standpoint. I would have created a method with only one purpose and then added an overload when I was ready, but I am not completely opposed to preparing for the future (not quite true, as this particular future may never be, but that is a topic for a rant post).

The top item is the more problematic item. let’s illustrate. Suppose someone sets up the enumeration array like so:

PurposeEnum[] enumValues = { PurposeEnum.LastValueToRun, PurposeEnum.MiddleValue, PurposeEnum.ShouldBeFirstValue };

Now imagine this order is important (as it is in the service I have) and I have code like this:

foreach(var purpose in enumValues)
{
AddToTree(context, purpose);
}

Even if we assume an array is guaranteed to keep objects in order rather than take a place on the heap, I now have a useless answer returned to the client consuming my service, as I need to ensure the Systems enum value is first.

Worse than that, I have tightly coupled my service to the client, as the client has to understand my array is not really an array, but an array with a set of business rules dictating order. Ouch!

To decouple, if I want to guarantee proper ordering, I have to employ something that ensures the value with primacy is first in the array, like the following code.

foreach(var purpose in purposesArray)
{
if(purpose == PurposeArray.Systems)
{
newArrayList.Add(purpose);
}
}

foreach(var purpose in purposesArray)
{
if(purpose != PurposeArray.Systems)
{
newArrayList.Add(purpose);
}
}

PurposeEnum[] newArray = newArrayList.ToArray();

The problem here is I end up with a lot of code just to keep ordering. Nasty! Nasty! Nasty!

There is an easy solution when ordering is important … (fanfare please) … Bitwise operations. In the case of an enum, this means [Flags]. If the PurposeEnum was set up with flags, it would appear like so:

[Flags]
public enum PurposeEnum
{
Systems = 1,
Accessories = 2,
Warranties = 34
}

You can actually simplify the above a bit, but the way I wrote it shows that the flags are binary in nature (each item is the value of the previous times 2). This is important, as using binary allows me to specify order internally without regard to whether the programmer consuming my code knows the proper order to get results.

Now, I can have a person simply send me a single value, and I can order based on business rules:

if((purpose && PurposeEnum.Systems) == PurposeEnum.Systems)
{
//Run the first item to set the tree up properly
}

//ETC

Either of these is fine from the client side, as they yield the same integer value:

var purposeArray = PurposeEnum.Systems || PurposeEnum.Accessories;
var purposeArray = PurposeEnum.Accessories || PurposeEnum.Systems;

The order is dicated by how I consume the enumeration, not the order in which the client places items on the stack.

This is not the only use of flags, nor the best use of flags. It is merely something I noticed today where I have to think about ordering of an array.

Peace and Grace,
Greg

Twitter: @gbworld

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: