Jun 09

Enums in .NET – part IV

Posted in .NET Basics C#      Comments Off on Enums in .NET – part IV

In the last post, we’ve started looking at the static methods introduced by the Enum type. In this post, we’ll take a quick look at the instance methods provided by that type. Before going into the methods (well, to be precise, I should say method:)), I’d like to make a small detour. I’m not sure that you’ve noticed, but the compiler treats enum as primitive types . In practice, this means that we can use several operators for comparing and manipulating enum instances (I’m reusing the Sizes enum introduced in the previous post):

var a = Sizes.Small;
var b = a – 1;//XSmall
var equals = b == Sizes.XSmall;//true

If you’ve been following along, then you’ve also probably noticed that we can explicitly cast an enumerated type value into a numeric type. Here’s some code that shows this:

var a = Sizes.Small;
var b = ( Int64 )a;//11L

And yes, you can also go the other way around:

var a = 11L;
var b = ( Sizes )a;//Sizes.Small

But there’s more: you can also rely on a cast to convert between different enums types:

var a = Sizes.Small;
var nonsense = ( Colors )a;//colors, without symbolic name

And now, back to business…

If you take a peek at the Enum API, you’ll notice that if offers several overloads of the ToString method (we’ll only talk about 2 because the other ones are considered deprecated). As we’ve seen, you can rely on this method to get an enum’s string equivalent representation. The overload that expects a string let’s you pass a value which identifies the format that should be used. Here’s some code that shows how to use this method:

var a = Sizes.Small;
Console.WriteLine( a.ToString() );//no param==general format
Console.WriteLine( a.ToString("X") );//hex:0B

Even though it’s not recommended (or even a good practice!), you can have several symbolic names refer to the same value. In this case, you don’t have any control over which name will be returned when you call the ToString method for formatting the value in the general format.

public enum Bad {
    Alias1 = 0,
    Alias2 = 0,
    Alias3 = 0

var a = Bad.Alias3;
Console.WriteLine( a.ToString() );//alias2 on my machine

On the other hand, if there’s no symbolic name for the current value, then the returned string will contain that value:

var c = ( Colors )10;
Console.WriteLine( c.ToString() );//"10"

The behavior of these ToString methods changes slightly when it notices that the current instance is a flags enum. Here’s an example (I’m reusing the Permissions enum from this post):

var perm = Permissions.Read | Permissions.Write;
Console.WriteLine( perm.ToString() );//"Write, Read"

When the ToString detects the FlagsAttribute applied to the current enum, it treats the current numeric value as a set of bits. In practice, this means that the current numeric value is ANDed with all the enum’s values. For each AND operation that returns true, that value’s associated symbolic name is added to a string and that bit is turned off. If after the end of this algorithm, the final value obtained from the ANDing operation isn’t zero, (recall that each “successful” AND turns off the “associated bits”) then the method knows that there aren’t symbolic names for all the turned on bits of the current numeric value and it will simply return a string with that numeric value.

Btw, if the flag enums has an all “All“ value which matches all the enum’s values and the current value matches that “All” value, then the ToString will return the “All”’s symbolic name. Here’s an example that shows this behavior:

var perm = Permissions.Read|Permissions.Write | Permissions.Special;
Console.WriteLine( perm.ToString() );//"All"

And that’s  for now. Stay tuned for more.