I am trying to understand how works the key sorting / insertion check in a hashtable. I've understood that when I'm adding an object to a hashtable, it checks at runtime that there isn't the same key already entered in there.
In my test, I've 2 hashtables which keys are filled in with: 1- Integers 2- An object which I've overriden the GetHashCode method to return always 1.
My issue here: while the first test is breaking when adding the same int key, the second test isn't! How come? The hashcodes that should be checked at the insertion are all returning 1.
Thank you in advance!
My code:
class Collections
{
public Collections()
{
// Testing a hashtable with integer keys
Dictionary<int, string> d1 = new Dictionary<int, string>();
d1.Add(1, "one");
d1.Add(2, "two");
d1.Add(3, "three");
// d1.Add(3, "three"); // Cannot add the same key, i.e. same hashcode
foreach (int key in d1.Keys)
Console.WriteLine(key);
// Testing a hashtable with objects returning only 1 as hashcode for its keys
Dictionary<Hashkey, string> d2 = new Dictionary<Hashkey, string>();
d2.Add(new Hashkey(1), "one");
d2.Add(new Hashkey(2), "two");
d2.Add(new Hashkey(3), "three");
d2.Add(new Hashkey(3), "three");
for (int i = 0; i < d2.Count; i++)
Console.WriteLine(d2.Keys.ElementAt(i).ToString());
}
}
/// <summary>
/// Creating a class that is serving as a key of a hasf table, overring the GetHashcode() of System.Object
/// </summary>
class Hashkey
{
public int Key { get; set; }
public Hashkey(int key)
{
this.Key = key;
}
// Overriding the Hashcode to return always 1
public override int GetHashCode()
{
return 1;
// return base.GetHashCode();
}
// No override
public override bool Equals(object obj)
{
return base.Equals(obj);
}
// returning the name of the object
public override string ToString()
{
return this.Key.ToString()开发者_运维知识库;
}
}
}
Dictionary
will check for the hash code and object equality. The hash is just used to come up with a "first approximation" to find possibly equal keys very efficiently.
Your override of Equals
just delegates to the base implementation, which uses reference equality. That means any two distinct instances of HashKey
are unequal, even if they have the same value for the Key
property.
What are you actually trying to achieve? Or are you just trying to understand how GetHashCode
and Equals
relate to each other?
The hash code is merely an heuristic to choose the right bucket to store the item in. Just because 2 items share the same hashcode doesn't mean that they are equal. In the case of collision (as will be occurring with your 1 hashcode), we revert to simple search within the bucket to find members that are equal to the searched key. As your equality test is checking if the references are the same, no 2 items will ever be equal.
The Equals
compares the reference of the HashKey
.
Because that are different instances, they are not equal.
Your Equals
should look like this:
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
return true;
var other = obj as Hashkey;
return
other != null &&
Key.Equals(other.Key);
}
精彩评论