Question

Referring to the question that I previously asked: Compare two lists that contain a lot of objects

It is impressive to see how fast that comparison is maide by implementing the IEqualityComparer interface: example here

As I mentioned in my other question this comparison helps me to backup a sourse folder on a destination folder. Know I want to sync to folders therefore I need to compare the dates of the files. Whenever I do something like:

public class MyFileComparer2 : IEqualityComparer<MyFile>
{

    public bool Equals(MyFile s, MyFile d)
    {
        return
            s.compareName.Equals(d.compareName) &&
            s.size == d.size &&
            s.deepness == d.deepness &&
            s.dateModified.Date <= d.dateModified.Date;  // This line does not work. 
            // I also tried comparing the strings by converting it to a string and it does
            // not work. It does not give me an error but it does not seem to include the files
            // where s.dateModified.Date < d.dateModified.Date

    }

    public int GetHashCode(MyFile a)
    {
        int rt = (a.compareName.GetHashCode() * 251 + a.size.GetHashCode() * 251 + a.deepness.GetHashCode() + a.dateModified.Date.GetHashCode());

        return rt;

    }
}

It will be nice if I could do something similar using greater or equal than signs. I also tried using the tick property and it does not work. Maybe I am doing something wrong. I believe it is not possible to compare things with the less than equal sign implementing this interface. Moreover, I don't understand how this Class works; I just know it is impressive how fast it iterates through the whole list.

Was it helpful?

Solution

Since the DateTime objects are different in the case when one DateTime is less than the other, you get different hashcodes for the objects s and d and the Equals method is not called. In order for your comparison of the dates to work, you should remove the date part from the GetHashCode method:

public int GetHashCode(MyFile a)
{
    int rt = ((a.compareName.GetHashCode() * 251 + a.size.GetHashCode())
                          * 251 + a.deepness.GetHashCode()) *251;

    return rt;

}

OTHER TIPS

Your whole approach is fundementally flawed because your IEqualityComparer.Equals method is not symmetric. This means Equals(file1, file2) does not equal Equals(file2, file1) because of the way you are using the less than operator.

The documentation:

clearly states:

Notes to Implementers

The Equals method is reflexive, symmetric, and transitive. That is, it returns true if used to compare an object with itself; true for two objects x and y if it is true for y and x; and true for two objects x and z if it is true for x and y and also true for y and z.

Implementations are required to ensure that if the Equals method returns true for two objects x and y, then the value returned by the GetHashCode method for x must equal the value returned for y.

Instead you need to use the IComparable interface or IEqualityComparer in combination with date comparisions. If you do not, things might seem to work for a while but you will regret it later.

Your GetHashCode has a problem:

public int GetHashCode(MyFile a)
{
    int rt = (((a.compareName.GetHashCode() * 251) 
           + a.size.GetHashCode() * 251)
           + a.deepness.GetHashCode() *251) 
           + a.dateModified.Date.GetHashCode();

    return rt;

}

I changed the date part because I also needed the time therefore I use the ticks property instead. I got rid of the dateModified hashed code and it works great. here is how I modified my program. I was having trouble comparing the dates therefore I used the Ticks property.

public class MyFileComparer2 : IEqualityComparer<MyFile>
{

    public bool Equals(MyFile s, MyFile d)
    {
        return
            s.compareName.Equals(d.compareName) &&
            s.size == d.size &&
            s.deepness == d.deepness &&
            //s.dateModified.Date <= d.dateModified.Date &&
            s.dateModified.Ticks >= d.dateModified.Ticks
            ;  

    }

    public int GetHashCode(MyFile a)
    {
        int rt = (((a.compareName.GetHashCode() * 251)
                + a.size.GetHashCode() * 251)
                + a.deepness.GetHashCode() * 251)
                //+ a.dateModified.Ticks.GetHashCode();                       
                ;

        return rt;

    }
}

I still don't know how this hash code function works. The nice thing is that it works great.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top