IEquatable<;T>;-C#中.Equals(对象obj)的最佳实践重写

本文关键字:obj 最佳 重写 对象 Equals lt gt -C# IEquatable | 更新日期: 2023-09-27 18:26:42

每当我写一个新的classstruct,它可能包含一些可能需要比较的数据时,我总是实现IEquatable<T>,因为这为class/struct提供了一个强类型的.Equals(T other)方法。

示例:

public struct Radius : IEquatable<Radius>
{
    public Int32 TopLeft { get; set; }
    public Int32 TopRight { get; set; }
    public Int32 BottomLeft { get; set; }
    public Int32 BottomRight { get; set; }
    public bool Equals(Radius other)
    {
        return this.TopLeft == other.TopLeft
            && this.TopRight == other.TopRight
            && this.BottomLeft == other.BottomLeft
            && this.BottomRight == other.BottomRight;
    }
}

除了提供.Equals(Radius other)的实现外,我还应该覆盖默认实现(.Equals(object obj)

我有两个选择,我的问题是,这些实现中哪一个更好?

选项1是使用铸造:

public override bool Equals(object obj)
{
    return this.Equals((Radius)obj);
}

选项2是使用"as"关键字:

public override bool Equals(object obj)
{
    return this.Equals(obj as Radius);
}

我问这个问题的原因是,如果obj不能强制转换为Radius,则使用强制转换将抛出异常,而如果不能强制转换,则as将解析为null,因此它只检查thisnull,而不抛出异常;那么,是抛出异常更好,还是只返回false更好呢?

编辑:正如许多SO同事所指出的,结构不能为null,因此第二个选项不适用于结构。因此,脑海中浮现出另一个问题:对于结构和类,.Equals(object obj)的重写实现是否应该相同?

IEquatable<;T>;-C#中.Equals(对象obj)的最佳实践重写

Equals()方法决不能引发异常。

不同类型的对象只是不平等的。

引用文件:

Equals的实现不能引发异常;它们应该始终返回一个值。例如,如果obj为null,Equals方法应该返回false,而不是抛出ArgumentNullException。

正如@SLaks已经提到的,Equals()永远不应该抛出。

在这种特殊情况下,我认为is运算符与强制转换的结合使用应该会帮助您:

public override bool Equals(object obj)
{
     if(obj is Radius)
         return Equals((Radius)obj);
     return false;
}

如果您有class,您只需使用as运算符:

public override bool Equals(object obj)
{
     return Equals(obj as MyObj);
}
public bool Equals(MyObj obj)
{
     if(ReferenceEquals(obj, null))
         return false;
     // ToDo: further checks for equality.
}

我个人的意见是使用第二个选项,甚至在手之前检查对象是否是"Radius",然后返回false,这样目的就更清楚了