IEqualityComparer未按预期工作

我有一个存储在我的计算机上的文件路径List 。 我的目的是首先筛选出具有相同名称的文件,然后筛选出具有相同大小的文件。
为此,我创建了两个实现IEqualityComparer ,并实现了EqualsGetHashCode方法。

 var query = FilesList.Distinct(new CustomTextComparer()) .Distinct(new CustomSizeComparer()); 

这两个类的代码如下: –

 public class CustomTextComparer : IEqualityComparer { public bool Equals(string x, string y) { if (Path.GetFileName(x) == Path.GetFileName(y)) { return true; } return false; } public int GetHashCode(string obj) { return obj.GetHashCode(); } } public class CustomSizeComparer : IEqualityComparer { public bool Equals(string x, string y) { if (new FileInfo(x).Length == new FileInfo(y).Length) { return true; } else { return false; } } public int GetHashCode(string obj) { return obj.GetHashCode(); } } 

但代码不起作用。

它不抛出任何exception,也没有任何编译器错误,但问题是代码不起作用(不排除重复文件)。

那么,我该如何纠正这个问题呢? 我能做些什么来使代码正常工作。

更改GetHashCode以处理比较值。 即你的尺寸比较:

 public int GetHashCode(string obj) { return FileInfo(x).Length.GetHashCode(); } 

对于另一个:

 public int GetHashCode(string obj) { return Path.GetFileName(obj).GetHashCode(); } 

根据这个答案 – GetHashCode在.NET中的IEqualityComparer 中的作用是什么? ,首先评估哈希码。 在发生碰撞时调用Equals

显然,处理FileInfo是合理的,而不是字符串。

也许吧:

 FileList.Select(x => new FileInfo(x)) .Distinct(new CustomTextComparer()) .Distinct(new CustomSizeComparer()); 

当然,您必须更改比较器才能使用正确的类型。

您的GetHashCode必须为具有相同值的任何对象返回相同的值:

 // Try this public int GetHashCode(string obj) { return Path.GetFileName(x).GetHashCode(); } // And this public int GetHashCode(string obj) { return new FileInfo(x).Length.GetHashCode(); } 

但是对于没有额外类的整个问题,这是一种更简单的方法:

 var query = FilesList .GroupBy(f => Path.GetFileName(f)).Select(g => g.First()) .GroupBy(f => new FileInfo(f).Length).Select(g => g.First()) .ToList(); 

在调用Equals之前使用哈希码。 由于您的代码为相同的项目提供了不同的哈希码,因此您无法获得所需的结果。 相反,当项目相同时,您必须确保返回的哈希码相等,例如:

 public class CustomTextComparer : IEqualityComparer { public bool Equals(string x, string y) { if (Path.GetFileName(x) == Path.GetFileName(y)) { return true; } return false; } public int GetHashCode(string obj) { return Path.GetFileName(obj).GetHashCode(); } } 

然而,正如Piotr指出的那样,这并不是一个很好的方法来实现你的目标,因为你将分别做很多 Path.GetFileNamenew FileInfo ,这将是一个重大的性能打击特别是因为你正在处理文件系统,因为它的响应速度并不完全清楚。