8

每次我写一些数据类时,我通常都会花很多时间来编写 IEquatable 实现。

我写的最后一节课是这样的:

public class Polygon
{
    public Point[] Vertices { get; set; }
}

实施 IEquatable 非常麻烦。当然 C#3.0/LINQ 有很大帮助,但是顶点可以移动和/或以相反的顺序移动,这给 Equals 方法增加了很多复杂性。经过多次单元测试和相应的实现,我放弃了,并将我的应用程序改为只接受三角形,而 IEquatable 实现只需要 11 个单元测试就可以完全覆盖。

有什么工具或技术可以帮助实现 Equals 和 GetHashCode?

4

2 回答 2

8

我使用 ReSharper 生成平等成员。如果您愿意,它可以选择实现IEquatable<T>和覆盖运算符(当然您永远不会这样做,但无论如何它很酷)。

Equals 的实现包括对Object.Equals(Object), 的覆盖以及强类型变体(可以避免不必要的类型检查)。较少类型的版本在执行类型检查后调用强类型版本。强类型版本执行引用相等检查 ( Object.ReferenceEquals(Object,Object)),然后比较所有字段的值(嗯,只有您告诉生成器包含的那些)。

至于,则组合了字段值GetHashCode的智能分解(如果您使用编译器的选项,则使用以避免溢出异常)。每个字段的值(除了第一个)在组合之前都乘以素数。您还可以指定哪些字段永远不会为空,它会删除任何空检查。GetHashCodeuncheckedchecked

Polygon这是您通过按下ALT+Insert然后选择“生成平等成员”为您的班级获得的内容:

public class Polygon : IEquatable<Polygon>
{
    public Point[] Vertices { get; set; }

    public bool Equals(Polygon other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return Equals(other.Vertices, Vertices);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof (Polygon)) return false;
        return Equals((Polygon) obj);
    }

    public override int GetHashCode()
    {
        return (Vertices != null ? Vertices.GetHashCode() : 0);
    }
}

我上面谈到的一些功能并不适用,因为只有一个字段。还要注意,它没有检查数组的内容。

但总的来说,ReSharper 在几秒钟内就可以输出大量优秀的代码。在我列出的使 ReSharper 成为如此出色的工具的事情列表中,该功能非常低。

于 2009-06-07T22:44:15.387 回答
2

为了比较两个项目数组,我使用SequenceEqual扩展方法。

至于通用的 Equals 和 GetHashCode,有一种基于序列化的技术可能对您有用。

使用 MemoryStream 和 BinaryFormatter 实现可重用的 GetHashCode 和 DeepCopy 函数

于 2009-06-07T23:22:55.527 回答