首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >值对象的IEqualityComparer

值对象的IEqualityComparer
EN

Stack Overflow用户
提问于 2009-10-14 11:18:01
回答 6查看 4K关注 0票数 1

我有一个不可变的值对象IPathwayModule,其值由以下方法定义:

  • (int)块;
  • (实体)模块,由(string) ModuleId标识;
  • (enum)状态;
  • (实体)类,由(string) ClassId标识--可能为空。

下面是我当前的IEqualityComparer实现,它似乎可以在几个单元测试中工作。然而,我认为我不知道我做的够好,也不知道我是否做得对。以前的实现有时会在重复测试运行时失败。

代码语言:javascript
复制
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?

  • Is有任何方法来提高健壮性,performance?

  • Are有什么好的实践是我没有遵循的?
EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-10-14 12:29:55

感谢所有回应的人。我收集了来自所有回复者的反馈,我改进的IEqualityComparer现在看起来如下:

代码语言:javascript
复制
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;
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2009-10-14 11:29:46

唯一的大问题是平等的实现。哈希代码不是唯一的,您可以为不同的对象获得相同的哈希代码。您应该单独比较IPathwayModule的每个字段。

GetHashCode()可以改进一点。不需要在int上调用GetHashCode()。int本身是一个很好的哈希代码。枚举值也是一样的。然后,您的GetHashCode可以这样实现:

代码语言:javascript
复制
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;
    }
}

“未检查”块是必要的,因为算术运算中可能存在溢出。

票数 3
EN

Stack Overflow用户

发布于 2009-10-14 11:24:30

不应该使用GetHashCode()作为比较对象的主要方式。把它从领域上比较。

可能有多个具有相同哈希代码的对象(这称为“哈希代码冲突”)。

此外,在将多个整数值相加时要小心,因为您可以很容易地导致OverflowException。使用“独占或”(^)组合哈希码或将代码包装到“未检查”块。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1565667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档