IEqualityComparer未按预期工作
我有一个存储在我的计算机上的文件路径List
。 我的目的是首先筛选出具有相同名称的文件,然后筛选出具有相同大小的文件。
为此,我创建了两个实现IEqualityComparer
,并实现了Equals
和GetHashCode
方法。
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.GetFileName
和new FileInfo
,这将是一个重大的性能打击特别是因为你正在处理文件系统,因为它的响应速度并不完全清楚。