等于方法实现助手(C#)

时间:2009-06-07 22:37:28

标签: c# .net equals gethashcode iequatable

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

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

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

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

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

2 个答案:

答案 0 :(得分:8)

我使用ReSharper生成相等的成员。如果你愿意的话,它可以选择实现IEquatable<T>以及覆盖运算符(当然你从来没有这样做,但它仍然很酷)。

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

对于GetHashCode,如果使用编译器的GetHashCode选项,则会合并字段unchecked值的智能因子分解(使用checked以避免溢出异常。在组合之前,每个字段的值(除第一个之外)乘以素数。您还可以指定哪些字段永远不会为空,并且它将丢弃任何空检查。

通过按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成为一个了不起的工具。

答案 1 :(得分:2)

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

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

Using MemoryStream and BinaryFormatter for reuseable GetHashCode and DeepCopy functions