我有一个不可变的值对象IPathwayModule,其值由以下方法定义:
下面是我当前的IEqualityComparer实现,它似乎可以在几个单元测试中工作。然而,我认为我不知道我做的够好,也不知道我是否做得对。以前的实现有时会在重复测试运行时失败。
private class StandardPathwayModuleComparer : IEqualityComparer<IPathwayModule>
{
public bool Equals(IPathwayModule x, IPathwayModule y)
{
int hx = GetHashCode(x);
int hy = GetHashCode(y);
return hx == hy;
}
public int GetHashCode(IPathwayModule obj)
{
int h;
if (obj.Class != null)
{
h = obj.Block.GetHashCode() + obj.Module.ModuleId.GetHashCode() + obj.Status.GetHashCode() + obj.Class.ClassId.GetHashCode();
}
else
{
h = obj.Block.GetHashCode() + obj.Module.ModuleId.GetHashCode() + obj.Status.GetHashCode() + "NOCLASS".GetHashCode();
}
return h;
}
}IPathwayModule绝对是不可变的,具有相同值的不同实例应该相等,并产生相同的HashCode,因为它们被用作HashSets中的项。
我想我的问题是:
在这种情况下,我是否正确地使用了接口?在这种情况下,我可能看不到想要的behaviour?
发布于 2009-10-14 12:29:55
感谢所有回应的人。我收集了来自所有回复者的反馈,我改进的IEqualityComparer现在看起来如下:
private class StandardPathwayModuleComparer : IEqualityComparer<IPathwayModule>
{
public bool Equals(IPathwayModule x, IPathwayModule y)
{
if (x == y) return true;
if (x == null || y == null) return false;
if ((x.Class == null) ^ (y.Class == null)) return false;
if (x.Class == null) //and implicitly y.Class == null
{
return x.Block.Equals(y.Block) && x.Status.Equals(y.Status) && x.Module.ModuleId.Equals(y.Module.ModuleId);
}
return x.Block.Equals(y.Block) && x.Status.Equals(y.Status) && x.Module.ModuleId.Equals(y.Module.ModuleId) && x.Class.ClassId.Equals(y.Class.ClassId);
}
public int GetHashCode(IPathwayModule obj)
{
unchecked {
int h = obj.Block ^ obj.Module.ModuleId.GetHashCode() ^ (int) obj.Status;
if (obj.Class != null)
{
h ^= obj.Class.ClassId.GetHashCode();
}
return h;
}
}
}发布于 2009-10-14 11:29:46
唯一的大问题是平等的实现。哈希代码不是唯一的,您可以为不同的对象获得相同的哈希代码。您应该单独比较IPathwayModule的每个字段。
GetHashCode()可以改进一点。不需要在int上调用GetHashCode()。int本身是一个很好的哈希代码。枚举值也是一样的。然后,您的GetHashCode可以这样实现:
public int GetHashCode(IPathwayModule obj)
{
unchecked {
int h = obj.Block + obj.Module.ModeleId.GetHashCode() + (int) obj.Status;
if (obj.class != null)
h += obj.Class.ClassId.GetHashCode();
return h;
}
}“未检查”块是必要的,因为算术运算中可能存在溢出。
发布于 2009-10-14 11:24:30
不应该使用GetHashCode()作为比较对象的主要方式。把它从领域上比较。
可能有多个具有相同哈希代码的对象(这称为“哈希代码冲突”)。
此外,在将多个整数值相加时要小心,因为您可以很容易地导致OverflowException。使用“独占或”(^)组合哈希码或将代码包装到“未检查”块。
https://stackoverflow.com/questions/1565667
复制相似问题