IEqualityComparer不按预期工作
我有一个List
存储在我的电脑上的文件路径。我的目标是首先筛选出具有相同名称的文件,然后筛选出具有相同大小的文件。
为此,我做了两类实施IEqualityComparer<string>
,并实施了Equals
和GetHashCode
的方法。IEqualityComparer不按预期工作
var query = FilesList.Distinct(new CustomTextComparer())
.Distinct(new CustomSizeComparer());
两个类的代码如下: -
public class CustomTextComparer : IEqualityComparer<string>
{
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<string>
{
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();
}
}
但代码不能正常工作。
它不会抛出任何异常,也没有任何编译器错误,但问题是代码不起作用(不排除重复的文件)。
那么,我该如何纠正这个问题呢?有什么我可以做的,使代码正常工作。
更改您的GetHashCode
以处理比较值。即为你的尺寸比较器:
public int GetHashCode(string obj)
{
return FileInfo(x).Length.GetHashCode();
}
而对于其他:
public int GetHashCode(string obj)
{
return Path.GetFileName(obj).GetHashCode();
}
根据这个答案 - What's the role of GetHashCode in the IEqualityComparer<T> in .NET?,哈希码首先计算。在发生碰撞时调用Equals
。
很明显,在FileInfo
上工作,而不是在字符串上工作。
所以也许:
FileList.Select(x => new FileInfo(x))
.Distinct(new CustomTextComparer())
.Distinct(new CustomSizeComparer());
当然,你必须改变你的comparers对正确类型的工作。
+1:只要实例相同,它们的散列码也必须相等,但如果散列码相等,则不一定意味着实例是平等的。 –
散列码在Equals被调用之前使用。由于您的代码为相同的项目提供了不同的哈希代码,因此您没有得到期望的结果。相反,你必须确保返回的哈希码等于当项目是相等的,因此,例如:
public class CustomTextComparer : IEqualityComparer<string>
{
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();
}
}
然而,正如彼得指出,这不正是去了解你的目标的好方法,因为你将要分别做批次的Path.GetFileName
和new FileInfo
,这将会是一个重大的性能问题,特别是在你处理文件系统时,它并不完全知道它的速度响应。
你的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();
+1为更简单的方法。 –
你标题并不反映问题的内容。请阅读[我如何写一个好的标题?](http://meta.stackexchange。com/questions/10647/how-do-i-write-a-good-title) –