locked
Using Enum as Index

    Question

  • If I have an enum such as

     

    public enum Test

    {

     One = 1,

     Two,

     Three

    }

     

    I want to be able to add a value based on the enumerated type such as:

    MyValue[Test.One] = 17;

    I would also like to keep ot strongly typesd so

    MyValue[1] = 17;

    is invalid.

    Is this possible within C#?

     

    Friday, January 19, 2007 8:22 PM

Answers

  • n0n4m3 is right about the cast. But if you want type safety you will have to program that in. I suggest you use a Dictionary object. I used int for the key but you could use the actual enumeration. In the example I show how to add to the array and enumerate it both as a dictionary and using the actual Enum object!


    public enum Enumbers
    {
        one = 1,
        next = 12,
        final = 100
    };

    public static void ENumber()
    {
        Dictionary<int, int> holdings = new Dictionary<int,int>();

        Enumbers en = Enumbers.next;

        // The following would go into its own method.
        if (holdings.ContainsKey((int)en) != true)
            holdings.Add((int)en, 17);

        en = Enumbers.final;

        if (holdings.ContainsKey((int)en) != true)
            holdings.Add((int)en, 999);

        foreach (KeyValuePair<int, int> item in holdings)
            Console.WriteLine("Key {0} Value {1}", item.Key, item.Value);

        Console.WriteLine("--- Show via enumerating enums");
        Type ops = typeof(Enumbers);

        foreach (Enumbers index in Enumbers.GetValues(ops))
            if (holdings.ContainsKey((int) index))
                Console.WriteLine("Key ({0}) {1} Value {2}", index.ToString(), (int) index,  holdings[(int) index]);
    }

     



    Console OutputKey 12 Value 17
    Key 100 Value 999
    --- Show via enumerating enums
    Key (next) 12 Value 17
    Key (final) 100 Value 999
    Friday, January 19, 2007 9:34 PM
    Moderator
  • Create a collection inherited from CollectionBase and don't put the default indexer which is like this:

    public int this[int index]
    {
       set { List[index] = value; }
       get { return (int) List[index]; }
    }

     

    Instead of that default indexer implement this one:

    [IndexerName("Item")]
    public int this[Test t]
    {
       set { List[(int)t] = value; }
       get { return (int) List[(int)]; }
    }

     

    But to be able to work you need to have special constructor that will create all items in collection and your enum to start from 0.
    Saturday, January 20, 2007 12:36 AM
  • Hi,

      you can use a dictionary which uses generics to give you type safety i.e.

     

    using System;

    using System.Collections.Generic;

     

    namespace ConsoleApplication1

    {

        class Program

        {

            public enum Test

            {

                One = 1,

                Two = 2,

                Hundred = 100

            }

     

            static void Main(string[] args)

            {

                Dictionary<Test, int> values = new Dictionary<Test, int>();

                values[Test.One] = 99;

                values[Test.Hundred] = 54;

     

                //compile error

                values[100] = 99;

            }

        }

    }

     

    Mark.

    Saturday, January 20, 2007 2:29 AM
  • Yes you can use the enumeration. But as some of the other posts mentioned one will need to handle any special situations of getting data in and out. But yes you can use the enum as a key. The dictionary object is generic and it could even hold other dictionaries as its values. Try it out in a console application to see if it meets your needs.
    Monday, January 22, 2007 4:43 AM
    Moderator

All replies

  • Hi,
    one possible solution is this:

    int[] MyValue = new int[10];
    MyValue[0] = 10;
    MyValue[(int)Test.One] = 20;

    Friday, January 19, 2007 8:32 PM
  • OK

     

    if I had

     

    public enum Test

    {

    One = 1,

    Two = 2,

    Hundred = 100

    }

     

    The array would be 3 elements so I could not use

    MyValues[(int)Test.Hundred] = 17;

    It also is not strongly typed, I could still implement

    MyValues[2] = 17;

    which I want to disallow or at least check

    Friday, January 19, 2007 9:28 PM
  • n0n4m3 is right about the cast. But if you want type safety you will have to program that in. I suggest you use a Dictionary object. I used int for the key but you could use the actual enumeration. In the example I show how to add to the array and enumerate it both as a dictionary and using the actual Enum object!


    public enum Enumbers
    {
        one = 1,
        next = 12,
        final = 100
    };

    public static void ENumber()
    {
        Dictionary<int, int> holdings = new Dictionary<int,int>();

        Enumbers en = Enumbers.next;

        // The following would go into its own method.
        if (holdings.ContainsKey((int)en) != true)
            holdings.Add((int)en, 17);

        en = Enumbers.final;

        if (holdings.ContainsKey((int)en) != true)
            holdings.Add((int)en, 999);

        foreach (KeyValuePair<int, int> item in holdings)
            Console.WriteLine("Key {0} Value {1}", item.Key, item.Value);

        Console.WriteLine("--- Show via enumerating enums");
        Type ops = typeof(Enumbers);

        foreach (Enumbers index in Enumbers.GetValues(ops))
            if (holdings.ContainsKey((int) index))
                Console.WriteLine("Key ({0}) {1} Value {2}", index.ToString(), (int) index,  holdings[(int) index]);
    }

     



    Console OutputKey 12 Value 17
    Key 100 Value 999
    --- Show via enumerating enums
    Key (next) 12 Value 17
    Key (final) 100 Value 999
    Friday, January 19, 2007 9:34 PM
    Moderator
  • Sorry about that, I misunderstood your question.
    In that case you should follow the Omegaman suggestion.
    Saturday, January 20, 2007 12:09 AM
  • Create a collection inherited from CollectionBase and don't put the default indexer which is like this:

    public int this[int index]
    {
       set { List[index] = value; }
       get { return (int) List[index]; }
    }

     

    Instead of that default indexer implement this one:

    [IndexerName("Item")]
    public int this[Test t]
    {
       set { List[(int)t] = value; }
       get { return (int) List[(int)]; }
    }

     

    But to be able to work you need to have special constructor that will create all items in collection and your enum to start from 0.
    Saturday, January 20, 2007 12:36 AM
  • Hi,

      you can use a dictionary which uses generics to give you type safety i.e.

     

    using System;

    using System.Collections.Generic;

     

    namespace ConsoleApplication1

    {

        class Program

        {

            public enum Test

            {

                One = 1,

                Two = 2,

                Hundred = 100

            }

     

            static void Main(string[] args)

            {

                Dictionary<Test, int> values = new Dictionary<Test, int>();

                values[Test.One] = 99;

                values[Test.Hundred] = 54;

     

                //compile error

                values[100] = 99;

            }

        }

    }

     

    Mark.

    Saturday, January 20, 2007 2:29 AM
  • OmegaMan,

    Could I change the dictionary entry to have the enumeration as the key

    public
    enum Enumbers
    {
        one = 1,
        next = 12,
        final = 100
    };

    public static void ENumber()
    {
        Dictionary<Enumbers, int> holdings = new Dictionary<
    Enumbers,int>();


    Would there be any benefits from doing it this way? Or are there disadvantages?
    Sunday, January 21, 2007 8:34 AM
  • Yes you can use the enumeration. But as some of the other posts mentioned one will need to handle any special situations of getting data in and out. But yes you can use the enum as a key. The dictionary object is generic and it could even hold other dictionaries as its values. Try it out in a console application to see if it meets your needs.
    Monday, January 22, 2007 4:43 AM
    Moderator
  • The absence of enum array indexing is an oversight.

    Defining and indexing Arrays is one of the key purposes of enums in C.

    The eventual inclusion this feature in C# will be significant, almost like generics.

    It would also be nice to have an enum constraint on generics.

    In fact, it would be nice to have:
    (1)  automatic DBNull to Nullable<T> conversion,
    (2) Nullable<T> and Object equivalency constraints
    ....

    My...
    $0.02

    Saturday, November 01, 2008 5:44 PM