6

I need to arrange sort of dictionary where the key would be a pair of enum and int and value is object. So I want to map a pair to some object.

One option would be

public enum SomeEnum
{
 value1, value2
}

class Key
{
  public SomeEnum;
  public int counter;  

  // Do I have to implement Compare here?
}

Dictionary<SomeEnum, object> _myDictionary;

Another option would convert enum and int to some unique key.

string key = String.Format("{0}/{1}", enumValue, intValue)

That approach requires string parsing, a lot of extra work.

How to make it easily?

Captain Comic
  • 15,744
  • 43
  • 110
  • 148

3 Answers3

9

I would go with something similar to

public enum SomeEnum
{
 value1, value2
}

public struct Key
{
  public SomeEnum;
  public int counter;  
}

Dictionary<Key, object>

I think that would make it?

Onkelborg
  • 3,927
  • 1
  • 19
  • 22
  • Yes, that is by far the simplest :) – leppie Oct 20 '10 at 09:11
  • How two keys would be compared by Dictionary? Does it use == or IComparable? – Captain Comic Oct 20 '10 at 09:13
  • 1
    It's a value type, so it will just perform a ==. I'm not sure about 32 bit systems, but on a 64 bit system I think it would just compare two memory locations since the enum and the int will fit into 64 bit, it's a cheap operation. On 32 bit it would probably (?) require a few more instructions? – Onkelborg Oct 20 '10 at 09:17
  • The advantage of this solution is performance, and simplicity. It's cheap to compare. But you can't control sorting, for example – Onkelborg Oct 20 '10 at 09:21
  • Hm, when I think about it, you can specify the order in which the fields are stored internally. That should allow you to specfiy internal relevance between the enum and the int – Onkelborg Oct 20 '10 at 09:26
9

If you are going to put this in a dictionary, then you will need to make sure you implement a meaningful .Equals and .GetHashCode or the dictionary will not behave correctly.

I'd start off with something like the following for the basic compound key, and then implement a custom IComparer to get the sort order you need.

public class MyKey
{
    private readonly SomeEnum enumeration;
    private readonly int number;

    public MyKey(SomeEnum enumeration, int number)
    {
        this.enumeration = enumeration;
        this.number = number;
    }

    public int Number
    {
        get { return number; }
    }

    public SomeEnum Enumeration
    {
        get { return enumeration; }
    }

    public override int GetHashCode()
    {
        int hash = 23 * 37 + this.enumeration.GetHashCode();
        hash = hash * 37 + this.number.GetHashCode();

        return hash;
    }

    public override bool Equals(object obj)
    {
        var supplied = obj as MyKey;
        if (supplied == null)
        {
            return false;
        }

        if (supplied.enumeration != this.enumeration)
        {
            return false;
        }

        if (supplied.number != this.number)
        {
            return false;
        }

        return true;
    }
}
Rob Levine
  • 40,328
  • 13
  • 85
  • 111
  • 2
    +1 for mentioning the .Equals and GetHashCode gotcha. This is a good reason to use the Tuple type instead of rolling your own simple key. – Winston Smith Oct 20 '10 at 09:18
  • I believe structures have default overrides of GetHashCode and Equals which will yield correct results, though the default GetHashCode simply hashes the first element in the structure. Performance will be good if most structures differ in the first element, and very bad if most structures have the same first element. – supercat Aug 23 '11 at 18:42
7

If you are using C# 4.0, you could use the Tuple class.

var key = Tuple.Create(SomeEnum.Value1, 3);
Winston Smith
  • 21,585
  • 10
  • 60
  • 75
  • 1
    Yes, but then it's not nicely typed - ie, there's not description of what the key consists of. But yes, it's possible – Onkelborg Oct 20 '10 at 09:14
  • 1
    It is strongly typed - the key is of type `Tuple`. – Winston Smith Oct 20 '10 at 09:15
  • 1
    So your dictionary could be defined as `Dictionary, object>` – Winston Smith Oct 20 '10 at 09:17
  • 1
    Yes, it's strongly typed, but it's not descriptive. If you later get a hold of that key, do you know what that integer really is? That's my point. It may, or may not, be a problem. It depends :) – Onkelborg Oct 20 '10 at 09:18
  • 1
    It's "strongly typed" but not "nicely typed". With a struct (or an anonymous type) you can access the members by x.NameYouSpecify. With a Tuple you access x.Item1, which is nowhere near as informative. – Iain Galloway Oct 20 '10 at 09:33