Question

In my class, I have implemented Equals and GetHashCode. yet when I use it as key for a dictionary in my C# code, I get the error : "Key not found exception" Thanks,

public class Time: IEquatable<Time>
{
    public String hour;
    public String minute;

    public Time()
    {
        hour = "00";
        minute = "00";
    }

    public Time(String hour, String minute)
        : this()
    {
        this.hour = hour;
        this.minute = minute;
    }

    public override int GetHashCode()
    {
        int hash = int.Parse(hour) * 60 + int.Parse(minute);
        return hash.GetHashCode();
    }
    public override bool Equals(Time time)
    {

            return (this.hour == time.hour && this.minute == time.minute);

    }

}

And The code where I am using it:

Dictionary<Time, int> time2RowIndex = new Dictionary<Time, int>();

...

int beginRow = 0;
if(time2RowIndex.ContainsKey(time.hour))
      beginRow = time2RowIndex [time.hour];
Was it helpful?

Solution

Try this. The trick is to override Equals from object (and GetHashCode) instead of just implementing IEquatable<>.

Also, if Hour or Minute on the Time object change after the instance of Time has been added to the dictionary, the bucket (selected by hash code at the time of the add) will no longer match the hash code on the object. This means that even if you present an object of equal value to the dictionary (say with ContainsKey), it won't find the original item in the dictionary (because the hash bucket it will look in doesn't contain the original object). It's a best practice that all fields referenced in the GetHashCode function be readonly to avoid these situations.

public class Time : IEquatable<Time>
{
    public String Hour;
    public String Minute;

    public Time()
    {
        Hour = "00";
        Minute = "00";
    }

    public Time(String hour, String minute)
        : this()
    {
        this.Hour = hour;
        this.Minute = minute;
    }

    public override int GetHashCode()
    {
        return int.Parse(Hour) * 60 + int.Parse(Minute);
    }

    public override bool Equals(object obj)
    {
        var time = obj as Time;
        return !ReferenceEquals(time, null) && Equals(time);
    }

    public bool Equals(Time time)
    {
        return string.Equals(Hour, time.Hour, StringComparison.Ordinal) && string.Equals(Minute, time.Minute, StringComparison.Ordinal);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top