9

Using C#, I'd like to find a way how to implement something like a dictionary that depends on two key objects.

I have an object and a string. To this two values I want to assign one double value. So what structure should I use? Or how can I implement such a structure?

DeanOC
  • 7,142
  • 6
  • 42
  • 56
  • 1
    Do you want to lookup by each key separatedly? If yes, then it nulifies most answers already given. – Euphoric Feb 27 '11 at 21:26
  • Do you need both the object and string to form a unique key, or is the object a unique key, and the string another unique key, and you want to be able to look up the value using either key? – Ben Voigt Feb 27 '11 at 21:26
  • @Euphoric and Ben Voigt I need both objects to form the unique key –  Feb 27 '11 at 21:28

5 Answers5

18

Try to use something like that

Dictionary<Tuple<object,string>,double>
Stecya
  • 22,896
  • 10
  • 72
  • 102
  • 1
    I didn't realize .net 4.0 added tuples, no more using KeyValuePair when needing to have a tuple of 2 objects! – Novikov Feb 27 '11 at 21:09
  • in 4.0 aslo is pretty nice thing as anonymous classes var temp = new { value1 = 2 ,value2 = "some string"} for temporary usages – Stecya Feb 27 '11 at 21:12
  • @Stecya C# 3 actually has anonymous types – RichK Feb 27 '11 at 22:13
  • @RichK can you explain that in more detail? Im using .net 3.5 as I should have stated maybe – RoflcoptrException Feb 27 '11 at 22:14
  • @Roflcopter I'm not sure anonymous types will help you with your problem I was just letting Stecya know that they're not exclusive to C# 4. If you want to learn more about anonymous types there are plenty of resources online to guide you. – RichK Feb 27 '11 at 22:20
  • Anonymous types won't help here since they have no name and thus you can't put them as type parameter into Dictionary. There are a few hacks based on generic inference that can work around that, but they are no good idea in this context. – CodesInChaos Feb 27 '11 at 22:44
7

You could have a custom class which aggregates the two properties, override the GetHashCode method on it and then have a IDictionary<CustomClass, double>.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
4

If you are using .NET 3.5 you can't use Tuples, because those were added in .NET 4.

But you can easily create class, that will contain both of your keys and that can be used as key in a dictionary. Only things to do is to override Equals() and GetHashCode() methods in your key class, so Dictionary can use it as a key correctly.

Those should be implemented logicaly by equating or hashing both of your keys. And some more related information : GetHashCode vs. Equals.

Community
  • 1
  • 1
Euphoric
  • 12,645
  • 1
  • 30
  • 44
2

You don't necessarily need to. If your object has overridden the GetHashCode member of Object.

Dictionary<string, double> myDict = new Dictionary<string, double>();

myDict[myObj.GetHashCode() + myString] = myDouble;
Novikov
  • 4,399
  • 3
  • 28
  • 36
  • With .net hashcodes it's kind of an iffy implementation. I've used this technique before with unique userids along with MD5 hashes (hexadecimal string) of files. It works much better when the two strings being concatenated are of an expected length since that kills the possibility of a collision. – Novikov Feb 27 '11 at 21:15
  • Completely broken. If two objects have the same HashCode they will get the same string-key and thus share a dictionary entry. – CodesInChaos Feb 27 '11 at 22:39
  • Objects that have the same HashCode would cause collisions even if you used just the object all by itself since the default comparer for Dictionaries relies on GetHashCode. – Novikov Feb 27 '11 at 23:32
  • The difference is that with the standard dictionary a collision means only a slight slow down(unless very many collide, in which case it will be a big slow down) but doesn't affect the correctness. With your code a collision means a bug. – CodesInChaos Feb 28 '11 at 08:35
  • Could you elaborate? Are strings treated differently than other objects? – Novikov Feb 28 '11 at 09:21
2

Create a class to be your key:

public class MyKey
{
    public String Str;
    public Object Obj;
}

Then:

Dictionary<MyKey, double> MyDict = new Dictionary<MyKey, double>();
Steve Wellens
  • 20,506
  • 2
  • 28
  • 69
  • 3
    That doesn't work without overriding `Equals` and `GetHashCode` since by default classes use referential equality. – CodesInChaos Feb 27 '11 at 22:39
  • It might work if you used a struct instead. But I didn't look deeply into the default implementation of struct equals. – CodesInChaos Feb 27 '11 at 22:46