Сравните два списка, содержащих много объектов (2-я часть)
-
14-11-2019 - |
Вопрос
Возвращаясь к вопросу, который я задавал ранее:Сравните два списка, которые содержат много объектов
Впечатляет, насколько быстро выполняется это сравнение благодаря реализации интерфейса IEqualityComparer: пример здесь
Как я уже упоминал в своем другом вопросе, это сравнение помогает мне создать резервную копию исходной папки в папке назначения.Знаю, что хочу синхронизировать папки, поэтому мне нужно сравнить даты файлов.Всякий раз, когда я делаю что-то вроде:
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;
}
}
Было бы неплохо, если бы я мог сделать что-то подобное, используя знаки «больше» или «равно».Я также пробовал использовать свойство галочки, но оно не работает.Возможно, я делаю что-то неправильно.Я считаю, что невозможно сравнивать вещи со знаком меньше, чем равно, реализующим этот интерфейс.Более того, я не понимаю, как работает этот класс;Я просто знаю, что впечатляет то, как быстро он проходит по всему списку.
Решение
Поскольку объекты DateTime отличаются в том случае, когда одно значение dateTime меньше, чем другое, вы получаете разные hashcodes для объектов s и d и метод равенстване вызывается.Для того, чтобы ваше сравнение датов на работу вы должны удалить часть даты из метода GetHashCode:
.public int GetHashCode(MyFile a)
{
int rt = ((a.compareName.GetHashCode() * 251 + a.size.GetHashCode())
* 251 + a.deepness.GetHashCode()) *251;
return rt;
}
Другие советы
Весь ваш подход в корне ошибочен, потому что ваш IEqualityComparer.Equals
метод не симметричен.Это означает Equals(file1, file2)
не равно Equals(file2, file1)
из-за того, как вы используете оператор «меньше».
Документация:
четко сказано:
Примечания для разработчиков
Метод Equals является рефлексивным, симметричным и транзитивным.То есть он возвращает true, если используется для сравнения объекта с самим собой;true для двух объектов x и y, если это верно для y и x;и истинно для двух объектов x и z, если оно верно для x и y, а также верно для y и z.
Реализации необходимы для того, чтобы гарантировать, что если метод Equals возвращает true для двух объектов x и y, то значение, возвращаемое методом GetHashCode для x, должно равняться значению, возвращаемому для y.
Вместо этого вам нужно использовать IComparable
интерфейс или IEqualityComparer
в сочетании со сравнением дат.Если вы этого не сделаете, какое-то время может показаться, что все работает, но позже вы пожалеете об этом.
Ваш GethashCode имеет проблему:
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;
}
. Я изменил часть даты, потому что мне также нужно время, поэтому вместо этого я использую свойство Ticks.Я избавился от DateModified Hashed Code, и он отлично работает.Вот как я изменил мою программу.У меня возникли проблемы с сравнением дат, поэтому я использовал свойство The Ticks.
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;
}
}
.
Я до сих пор не знаю, как работает этот хэш-код функции.Приятно, что он отлично работает.