IEquatable<;T>;-C#中.Equals(对象obj)的最佳实践重写
本文关键字:obj 最佳 重写 对象 Equals lt gt -C# IEquatable | 更新日期: 2023-09-27 18:26:42
每当我写一个新的class
或struct
,它可能包含一些可能需要比较的数据时,我总是实现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
,因此它只检查this
和null
,而不抛出异常;那么,是抛出异常更好,还是只返回false
更好呢?
编辑:正如许多SO同事所指出的,结构不能为null,因此第二个选项不适用于结构。因此,脑海中浮现出另一个问题:对于结构和类,.Equals(object 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,这样目的就更清楚了