-1

I'm having a problem in using the Dictionary ContainsKey method. although I'm overriding the Equals and GetHashCode methods, I'm always getting the value true.

What am I missing?

The FreeTime objects contains 2 variables of the type DateTime (start and end).

Here is the full class

class FreeTime : IEquatable<FreeTime>
{ 
    #region Constants

    private const bool FirstDayOfWeekIsMonday = true;

    #endregion

    #region Private Variables

    private DateTime start;
    private DateTime end;
    private static bool TodayIsSunday = (int)DateTime.Today.DayOfWeek == 0;


    #endregion

    #region Public Fields

    public DateTime Start { get { return start; } }

    public DateTime End { get { return end; } }

    public void setStart(DateTime startValue) { start = startValue; }

    public void setEnd(DateTime EndValue) { end = EndValue; }

    #endregion

    #region Constructor

    public FreeTime()
    {
        start = DateTime.Today;
       end = DateTime.Today;
    }

    public FreeTime(DateTime s,DateTime e)
    {
        start = s;
        end = e;
    }

    #endregion

    public enum PeriodType
    {
        SingleMonth,
        AllMonths,
        InterveningMonths
    }
    public bool Equals(FreeTime other)
    {

        ////Check whether the compared object is null.  
        //if (Object.ReferenceEquals(other, null)) return false;

        //Check wether the products' properties are equal.  
        return start.Equals(other.start) && end.Equals(other.end);
    }


    public override int GetHashCode()
    {

        //Get hash code for the start field if it is not null.  
        int hashStart = start == null ? 0 : start.GetHashCode();

        //Get hash code for the end field.  
        int hashEnd = end.GetHashCode();

        //Calculate the hash code .  
        return hashStart ^ hashEnd;
    }

'

this is how I am using the containKey method

    Dictionary<FreeTime, string> FreeBusy = new Dictionary<FreeTime, string>();      
     if (FreeBusy.ContainsKey(intersection))      

but I am always geeting the value True

Irwene
  • 2,807
  • 23
  • 48
Ran
  • 57
  • 6
  • 2
    Are you overloading the `Equals(object)` method? – xanatos Jun 23 '15 at 14:48
  • Can you show the entire class and some sample data? – Patrick Hofman Jun 23 '15 at 14:49
  • 1
    I recommend a bit of reading : [what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode](http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode) – Thomas Ayoub Jun 23 '15 at 14:50
  • This is the full class – Ran Jun 23 '15 at 15:00
  • yes I am overloading it – Ran Jun 23 '15 at 15:03
  • Are you using the FreeTime object as your key in your dictionary? – Ryan Bennett Jun 23 '15 at 15:04
  • yes, the FreeTime object is my key – Ran Jun 23 '15 at 15:06
  • 1
    You need to provide a *complete* example that is able to reproduce the problem. You've now shown the class itself, but you've not shown how you're using it at all, and we have no way of reproducing the problem. Keep in mind that you should make your example as small as possible, with *only* as much code as is needed to reproduce the problem. – Servy Jun 23 '15 at 15:06
  • Thank you .. I edited the question and added the detail to amke it understandable – Ran Jun 23 '15 at 15:14
  • 1
    Two things. Firstly use auto-properties for start and end - it will make your code shorter and clearer. Secondly, does this compile? `int hashStart = start == null ? 0 : start.GetHashCode();` looks wrong as `start` isn't nullable. EDIT: yes, it does compile, but it's clearly wrong to check a `DateTime` for null. – Andy Nichols Jun 23 '15 at 15:19

2 Answers2

0

you need also to overwrite the object.Equals method. just add the function

public override bool Equals(object obj)
{
    if (obj is FreeTime)
        return false;
    return Equals((FreeTime)obj);
}

(you are just implementing the IEquatable.Equals method, not the object.Equals method which has a generic argument)

user287107
  • 9,286
  • 1
  • 31
  • 47
  • Thank you for your reply,I added this function to my code but still getting only true !! – Ran Jun 23 '15 at 17:49
0

Here's the code behind the ContainsKey function:

public bool ContainsKey(TKey key) {
    return FindEntry(key) >= 0;
}
// Some code
private int FindEntry(TKey key) {
    if( key == null) {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
    }

    if (buckets != null) {
        int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
        for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
            if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
        }
    }
    return -1;
}

It's impossible that this code returns true:

Dictionary<FreeTime, string> FreeBusy = new Dictionary<FreeTime, string>();      
if (FreeBusy.ContainsKey(intersection))

Since the dictionary is empty.


And this code:

internal class FreeTime : IEquatable<FreeTime>
{
    #region Constants

    private const bool FirstDayOfWeekIsMonday = true;

    #endregion

    #region Private Variables

    private static bool TodayIsSunday = (int) DateTime.Today.DayOfWeek == 0;


    #endregion

    #region Public Fields

    public DateTime Start { get; set; }

    public DateTime End { get; set; }

    #endregion

    #region Constructor

    public FreeTime()
    {
        Start = End = DateTime.Today;
    }

    public FreeTime(DateTime s, DateTime e)
    {
        Start = s;
        End = e;
    }

    #endregion

    public enum PeriodType
    {
        SingleMonth,
        AllMonths,
        InterveningMonths
    }

    public bool Equals(FreeTime other)
    {

        ////Check whether the compared object is null.  
        //if (Object.ReferenceEquals(other, null)) return false;

        //Check wether the products' properties are equal.  
        return Start.Equals(other.Start) && End.Equals(other.End);
    }


    public override int GetHashCode()
    {

        //Get hash code for the start field if it is not null.  
        int hashStart = Start.GetHashCode();

        //Get hash code for the end field.  
        int hashEnd = End.GetHashCode();

        //Calculate the hash code .  
        return hashStart ^ hashEnd;
    }
}

works well on my computer.

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
  • No the dictionary is not empty , but I didnt show the method that fills the dictionary in here .. Thank you all for your reply, if it is working with you then it seems I'm having the problem somewhere else .. I'll try to find out .. thanks again – Ran Jun 24 '15 at 09:55
  • @Ran provide more code and we'll be able to help you :) – Thomas Ayoub Jun 24 '15 at 10:02