Enums in .NET – part II

In the previous post I’ve introduced the concept of enumerated type. As I’ve said, we can resort to an enumerated type to introduce several symbolic names/values pairs. As we’ve seen, enum are transformed into structs which extend the Enum type. During this transformation, the compiler ends up adding constants fields to the struct. By default, ints (System.Int32) are used as the default type for each of these constants. You can change this type by changing the enum’s underlying type:

public enum Sizes:long { //each value stored in Int64
    XSmall,//0
    Small, //1
    Medium, //2
    Large,//3
    XLarge//4
}

When the compiler finds the previous enum, it will transform each of the symbolic values into Int64 constants. Besides long, you can also use one of the following primitive types as an enum underlying type: byte, sbyte, short, ushort, int, uint, long, ulong. Notice that (unfortunately!) the compiler forces you to use the C# primitive type name (alias). If you try to use the FCL name, then you’ll end up with a compiler error:

public enum Sizes:Int64 { //compiler error
    XSmall,//0
    Small, //1
    Medium, //2
    Large,//3
    XLarge//4
}

Besides setting the underlying type, you can also be explicit about the values associated with each symbolic name:

public enum Sizes:long { //compiler error
    XSmall=10,//0
    Small, //no value: previous + 1->11
    Medium=20, //20
    Large=30,//30
    XLarge//31
}

As you can see, if you can resort to an attribution if you want to be explicit about the value of symbolic name. If you don’t set a symbolic name’s value explicitly, then it will add one to the previous value (that’s why Sizes.Small has value 11).

Enums can also be used as flags (aka bit flags).  Here’s an example:

[Flags]
public enum Permissions {
    Write = 1,  //001
    Read = 2,   //010
    Special = 4 //100
}

In the previous example, we’re using an enum to express a set of bits which can be combined (unlike “normal” enumerated types’ values). Notice also how each symbolic name’s value is defined so that it will only “turn on” a single bit (the comments show the integer represented in binary). In practice, the previous enum allow us to write code like this:

var permissions = Permissions.Read | Permissions.Write;//011

After grabing an enum value, you can check if a specific bit is “on” with code like this:

//checking for read permission
var hasRead = ( Permissions.Read & permissions ) == Permissions.Read;

Even though the previous Permissions enum definition is enough to explain the usage and purpose of flag enums, it wouldn’t be complete without presenting a couple of recommendations associated with its use. So, besides ensuring that each symbolic name’s value will have a single bit turned on, it’s also common to introduce a value called None and the combinations of the most used values. Let’s update our Permissions enum to reflect these recommendations:

[Flags]
public enum Permissions {
    None = 0,
    Write = 1,  //001
    Read = 2,   //010
    Special = 4, //100
    All = Write | Read | Special
}

And I guess that’s it for now. Stay tuned for more.

Advertisements

~ by Luis Abreu on June 7, 2011.

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: