每当我写一个可能包含某些数据的新class
或struct
时,可能需要对其进行比较,我总是实施IEquatable<T>
,因为这会提供{{1}使用强类型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)
)
我这里有两个选项,我的问题是,哪些实现更好?
选项1是使用强制转换:
.Equals(object obj)
选项2是使用“as”关键字:
public override bool Equals(object obj)
{
return this.Equals((Radius)obj);
}
我提出这个问题的原因是,如果无法将public override bool Equals(object obj)
{
return this.Equals(obj as Radius);
}
强制转换为obj
,则使用强制转换会抛出异常,而Radius
如果不能强制转换为as
因此,它只会null
对this
进行检查,而不会抛出异常;那么抛出异常或者只返回null
?
false
被覆盖的实现是否应该与结构和类相同?
答案 0 :(得分:7)
Equals()
方法must never throw an exception。
不同类型的对象仅仅是不相等的。
Equals的实现不得抛出异常;他们应该总是返回一个值。例如,如果obj为null,则Equals方法应该返回false而不是抛出ArgumentNullException。
答案 1 :(得分:5)
正如@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.
}
答案 2 :(得分:-1)
我个人的意见是使用第二个选项,或者如果对象是“Radius”,则甚至事先检查然后返回false以使意图更清晰