3

Using System.Collections how to create a collection with two primary keys ?

I mean new entries with the same combination are avoided but each key can be used with other keys (like combining two primary keys in SQL)

Xaqron
  • 29,931
  • 42
  • 140
  • 205
  • 1
    I think the term you are looking for is Composite Key or Compound Key. A key with two attributes is still just ONE key, not two. – nvogel Jan 14 '11 at 16:40

4 Answers4

5

You can simply use a struct, example:

struct CompositeKey<T1,T2>
{
  public T1 Item1;
  public T2 Item2;
}

Then use that as the key.

leppie
  • 115,091
  • 17
  • 196
  • 297
  • Note that structs might not work as intended if you're using a Dictionary for performance reasons. See "[How does native implementation of ValueType.GetHashCode work?](http://stackoverflow.com/a/5927853/579344)". – johv Nov 07 '13 at 12:21
  • @johv: Hash codes need not be unique, also .NET handles a few collisions quite fast. Many collisions obviously will be an issue. – leppie Nov 07 '13 at 13:53
  • I find the default implementation for structs quite surprising and non-intuitive. I had expected something closer to what Tuples provide. – johv Nov 07 '13 at 23:49
  • @johv: And then we can compare anonymous types too :) My way was just to show a very easy way that should be good 95% of time. – leppie Nov 08 '13 at 05:00
  • But is it really "good 95% of time"? How would the hashcode of a struct with two strings be calculated? Using just the first of the strings? I guess you're correct if by 95% of the time, you mean when linear search access time is okay. – johv Nov 11 '13 at 14:39
2

Like LaGrandMere said, you can use System.Tuple if you're on .NET 4.0 or later:

Tuple<int,string> key = Tuple.Create(0, "Test");

Also, note that if you're putting strings, ints etc as keys in dictionaries you're going to have to special-case what would've been NULL in SQL. Can't have a null-key in a Dictionary.

var dict = new Dictionary<Tuple<string, int>, string>();

var address1 = Tuple.Create("5th Avenue",15);
var address2 = Tuple.Create("5th Avenue",25);
var address3 = Tuple.Create("Dag Hammarskjölds väg", 4);

dict[address1] = "Donald";
dict[address2] = "Bob";
dict[address3] = "Kalle";

// ...

int number = Int32.Parse("25");
var addressKey = Tuple.Create("5th Avenue",number);
string name = dict[addressKey]; // Bob
johv
  • 4,424
  • 3
  • 26
  • 42
2

You can use Tuple if you're using .NET 4.0.

Else you can create a Tuple by yourself.

Found on StackOverFlow : Tuples( or arrays ) as Dictionary keys in C#

struct Tuple<T, U, W> : IEquatable<Tuple<T,U,W>>
{
    readonly T first;
    readonly U second;
    readonly W third;

    public Tuple(T first, U second, W third)
    {
        this.first = first;
        this.second = second;
        this.third = third;
    }

    public T First { get { return first; } }
    public U Second { get { return second; } }
    public W Third { get { return third; } }

    public override int GetHashCode()
    {
        return first.GetHashCode() ^ second.GetHashCode() ^ third.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (obj == null || GetType() != obj.GetType())
        {
            return false;
        }
        return Equals((Tuple<T, U, W>)obj);
    }

    public bool Equals(Tuple<T, U, W> other)
    {
        return other.first.Equals(first) && other.second.Equals(second) && other.third.Equals(third);
    }
}
Community
  • 1
  • 1
LaGrandMere
  • 10,265
  • 1
  • 33
  • 41
0

you can also construct composite key and use that in dictionary

var compositeKey = key1.ToString()+key2.ToString();

var dict = new Dictionary<string,object>();
dict.Add(compositekey,val);
LP13
  • 30,567
  • 53
  • 217
  • 400