指的是我之前问过的问题:比较包含大量对象的两个列表
令人印象深刻的是,通过实现IEqualityComparer接口,这种比较的速度有多快:这里的例子在这里
正如我在另一个问题中提到的,这种比较有助于我在目标文件夹上备份 soure 文件夹。知道我想同步到文件夹,因此我需要比较文件的日期。每当我做这样的事情时:
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;
}
}
如果我可以使用大于或等于符号来做类似的事情,那就太好了。我也尝试使用 tick 属性,但它不起作用。也许我做错了什么。我相信不可能将事物与实现此接口的小于等号进行比较。此外,我不明白这个类是如何工作的;我只知道它迭代整个列表的速度令人印象深刻。
你的整个方法在根本上是有缺陷的,因为你的IEqualityComparer.Equals
方法不是对称的。 这意味着Equals(file1, file2)
不等于Equals(file2, file1)
,因为您使用小于运算符的方式。
文档:
- IEqualityComparer.Equals Method
明确指出:
实施者须知
等于方法是自反的、对称的和传递的。也就是说,如果用于将对象与自身进行比较,则返回 true;如果对 y 和 x 为真,则对两个对象 x 和 y 为真;如果对 x 和 y 为真,则对两个对象 x 和 z 为真,对 y 和 z 也为真。
需要实现来确保如果 Equals 方法对两个对象 x 和 y 返回 true,则 x 的 GetHashCode 方法返回的值必须等于为 y 返回的值。
相反,您需要将IComparable
界面或IEqualityComparer
与日期比较结合使用。 如果你不这样做,事情似乎可以工作一段时间,但你以后会后悔的。
由于当一个 DateTime 小于另一个 DateTime 时,DateTime 对象是不同的,因此对象 s 和 d 的哈希代码不同,并且不会调用 Equals 方法。为了使日期比较有效,您应该从 GetHashCode 方法中删除日期部分:
public int GetHashCode(MyFile a)
{
int rt = ((a.compareName.GetHashCode() * 251 + a.size.GetHashCode())
* 251 + a.deepness.GetHashCode()) *251;
return rt;
}
你的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 属性。我摆脱了日期修改的散列代码,效果很好。这是我修改程序的方式。我在比较日期时遇到问题,因此我使用了 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;
}
}
我仍然不知道这个哈希代码函数是如何工作的。好消息是它工作得很好。