Indexing arrays by Enums

M

Mike Scott

What is the best way to index an array by an enum. Pascal has a nice feature
in that arrays can be indexed by an enum, for example

type
ButtonType = ( Left, Middle, Right ) ;

var
buttons : array[ ButtonType ] of Button ;

....
buttons[ Left ].Enabled := true ;


It appears that the only way to do this in C# is to cast the enum into an
integer, eg

enum ButtonType { Left, Middle, Right ) ;

Button[] buttons = new Button[ (int) ButtonType.Right + 1 ] ;

......
buttons[ (int) ButtonType.Left ].Enabled = true ;


Apart from the fact that the C# code is a lot less elegant and looks messy
with all the horrible casting, it's also not possible for the compiler to
check properly. Also if it becomes necessary to add another item to the enum
then you have to go through all the code and change the array declarations
and make sure that you have taken care of all the places that need changing.

In Pascal the compiler would automatically get the array declarations right
and would also flag up cases where you would need to make changes to take
care of the extra enum, eg. when walking through all items in the array.

Is there a better way of doing this in C#?

Has there been any discussion of adding arrays indexed by enums to the C#
language in the future?

Cheers

MikeS.
 
M

Maciej Kromrych

Mike,

[cut]
Button[] buttons = new Button[ (int) ButtonType.Right + 1 ] ; [cut]
check properly. Also if it becomes necessary to add another item to the enum
then you have to go through all the code and change the array declarations
and make sure that you have taken care of all the places that need
changing.

In C# you can declare an array like this:
Button[] buttons =
new Button[System.Enum.GetValues(typeof(ButtonType)).Length]
Now, if you add/remove items from the enum, size of the array
should always be ok.

HTH,
Maciej
 
J

Jay B. Harlow [MVP - Outlook]

Mike,
The way I do this is to encapsulate the downcast. I create a new class that
has an indexer with a parameter of the Enum type. I would have a private
member that contained the actual array, or a hashtable depending on if the
enum had sparse numbers or not. (sparse enum = [Flags] enum ButtonType {
Left = 1, Middle =2 , Right = 4, Top = 8, Bottom = 16 })

I would have this new class implement either ICollection or IList depending
on how flexible I wanted it. Of course inheriting DictionaryBase would
simplify the code. Inheriting CollectionBase in this regard doesn't really
make sense, as we want it indexed by the Enum, not a dynamic collection.

You can use Enum.GetValues().Length or Enum.GetNames().Length to find the
number of values in an enum, so in the constructor of the above class, you
would not need to 'hard code' the number of elements. Also a HashTable would
not be constrained by number of elements, and would support the
FlagsAttribute better.

Hope this helps
Jay
 
M

Mike Scott

Hi Jay,

Unfortunately Enum.GetValues() and Enum.GetNames() are not supported on the
Compact Framework :-(

Also it's a bit of a chore to have to create a whole wrapper class just to
create a little array indexed by an enum - A one line declaration in Pascal
:-(

Cheers

MikeS.

Jay B. Harlow said:
Mike,
The way I do this is to encapsulate the downcast. I create a new class that
has an indexer with a parameter of the Enum type. I would have a private
member that contained the actual array, or a hashtable depending on if the
enum had sparse numbers or not. (sparse enum = [Flags] enum ButtonType {
Left = 1, Middle =2 , Right = 4, Top = 8, Bottom = 16 })

I would have this new class implement either ICollection or IList depending
on how flexible I wanted it. Of course inheriting DictionaryBase would
simplify the code. Inheriting CollectionBase in this regard doesn't really
make sense, as we want it indexed by the Enum, not a dynamic collection.

You can use Enum.GetValues().Length or Enum.GetNames().Length to find the
number of values in an enum, so in the constructor of the above class, you
would not need to 'hard code' the number of elements. Also a HashTable would
not be constrained by number of elements, and would support the
FlagsAttribute better.

Hope this helps
Jay

Mike Scott said:
What is the best way to index an array by an enum. Pascal has a nice feature
in that arrays can be indexed by an enum, for example

type
ButtonType = ( Left, Middle, Right ) ;

var
buttons : array[ ButtonType ] of Button ;

...
buttons[ Left ].Enabled := true ;


It appears that the only way to do this in C# is to cast the enum into an
integer, eg

enum ButtonType { Left, Middle, Right ) ;

Button[] buttons = new Button[ (int) ButtonType.Right + 1 ] ;

.....
buttons[ (int) ButtonType.Left ].Enabled = true ;


Apart from the fact that the C# code is a lot less elegant and looks messy
with all the horrible casting, it's also not possible for the compiler to
check properly. Also if it becomes necessary to add another item to the enum
then you have to go through all the code and change the array declarations
and make sure that you have taken care of all the places that need changing.

In Pascal the compiler would automatically get the array declarations right
and would also flag up cases where you would need to make changes to take
care of the extra enum, eg. when walking through all items in the array.

Is there a better way of doing this in C#?

Has there been any discussion of adding arrays indexed by enums to the C#
language in the future?

Cheers

MikeS.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top