4

每当我写一个新的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不能强制转换则将解析为,因此它只是检查,而不抛出异常;那么是抛出异常还是仅仅返回更好呢?Radiusasnullthisnullfalse

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

4

3 回答 3

7

Equals()方法绝不能抛出异常

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

引用文档

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

于 2013-08-07T15:34:22.490 回答
5

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

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

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

     return false;
}

如果您有 a 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.
}
于 2013-08-08T09:12:04.040 回答
-1

我个人的意见是使用第二个选项,甚至事先检查对象是否是“半径”,然后返回 false 以便意图更清楚

于 2013-08-07T15:35:31.843 回答