Dictionary.ContainsKey(object)

A

Al Meadows

I'm using a generic Dictionary object where it is described as:

Dictionary<this, that> stuff = new Dictonary<this, that>()

Where THIS is a class with several property values.

This works fine as far as adding the key/value pairs to the dictionary.

The problem is when I contruct a new THIS object:

This this = new This();
this.a = "a";
this.b = "b";

and try to get a hit on:
if (stuff.ContainsKey(this))
{
...
}

Note: It works GREAT if I add this to the 'stuff' dictionary and then look
for the key, but not when I contruct a new key and try to match it to the
dictionary.

From research, I understand that it is because the dictionary object stores
a hash table value instead of the actual object as the key or something like
that and that is why they won't find it when I use Contains.

So, how do I work around this?
 
P

Peter Duniho

Al said:
[...]
From research, I understand that it is because the dictionary object stores
a hash table value instead of the actual object as the key or something like
that and that is why they won't find it when I use Contains.

So, how do I work around this?

Your "This" class needs to implement a custom hash that depends on the
contents (ie override Object.GetHashCode()). By default, the reference
itself is used for hashing, and so two different instances result in two
different hash values.

By the way, for future reference, you may want to avoid using the word
"this" as your class name or variable name, given that it has very
specific, special meaning in C#. :)

Pete
 
A

Andreas Mueller

Al said:
I'm using a generic Dictionary object where it is described as:

Dictionary<this, that> stuff = new Dictonary<this, that>()

Where THIS is a class with several property values.

This works fine as far as adding the key/value pairs to the dictionary.

The problem is when I contruct a new THIS object:

This this = new This();
this.a = "a";
this.b = "b";

and try to get a hit on:
if (stuff.ContainsKey(this))
{
...
}

Note: It works GREAT if I add this to the 'stuff' dictionary and then look
for the key, but not when I contruct a new key and try to match it to the
dictionary.

From research, I understand that it is because the dictionary object stores
a hash table value instead of the actual object as the key or something like
that and that is why they won't find it when I use Contains.

So, how do I work around this?

Hi,

you either have to override Equals and GetHashCode of your class or
implement a custom EqualityProvider for it:

class This
{
public string a, b;
public override bool Equals(object obj)
{
This rhs = obj as This;
if(rhs == null)
return false;
return Equals(a, rhs.a) && Equals(b, rhs.b);
}
public override int GetHashCode()
{
return a.GetHashCode() ^ b.GetHashCode();
}
}

class ThisEqualityComparer : IEqualityComparer<This>
{
public bool Equals(This x, This y)
{
return Equals(x.a, y.a) && Equals(x.b, y.b);
}

public int GetHashCode(This obj)
{
return obj.a.GetHashCode() ^ obj.b.GetHashCode();
}
}

IDictionary<This, That> stuff =
new Dictionary<This, That>(new ThisEqualityComparer())


HTH,
Andy
 
A

Andreas Mueller

Al said:
I'm using a generic Dictionary object where it is described as:

Dictionary<this, that> stuff = new Dictonary<this, that>()

Where THIS is a class with several property values.

This works fine as far as adding the key/value pairs to the dictionary.

The problem is when I contruct a new THIS object:

This this = new This();
this.a = "a";
this.b = "b";

and try to get a hit on:
if (stuff.ContainsKey(this))
{
...
}

Note: It works GREAT if I add this to the 'stuff' dictionary and then look
for the key, but not when I contruct a new key and try to match it to the
dictionary.

From research, I understand that it is because the dictionary object stores
a hash table value instead of the actual object as the key or something like
that and that is why they won't find it when I use Contains.

So, how do I work around this?
Hi,

you either have to override Equals and GetHashCode of your class or
implement a custom EqualityProvider for it:

class This
{
public string a, b;
public override bool Equals(object obj)
{
This rhs = obj as This;
if(rhs == null)
return false;
return Equals(a, rhs.a) && Equals(b, rhs.b);
}
public override int GetHashCode()
{
return a.GetHashCode() ^ b.GetHashCode();
}
}

class ThisEqualityComparer : IEqualityComparer<This>
{
public bool Equals(This x, This y)
{
return Equals(x.a, y.a) && Equals(x.b, y.b);
}

public int GetHashCode(This obj)
{
return obj.a.GetHashCode() ^ obj.b.GetHashCode();
}
}

IDictionary<This, That> stuff =
new Dictionary<This, That>(new ThisEqualityComparer())


HTH,
Andy
 

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