【发布时间】:2013-08-09 01:51:26
【问题描述】:
每当我编写一个新的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,因此它只检查@987654335 @反对null,不抛出异常;那么是抛出异常更好,还是只返回false?
编辑:正如许多 SO'ers 所指出的,结构不能为空,因此第二个选项不适用于结构。因此另一个问题浮现在脑海中:.Equals(object obj) 的覆盖实现对于结构和类是否应该相同?
【问题讨论】:
-
如果
other为空,您的Equals(Radius)方法应返回false,否则将抛出空输入异常。 -
@cdhowie 是一个结构体,不能为空。
-
您不能使用
as关键字,因为Radius不是可空类型。您应该改用is为其他类型返回 false,然后进行强制转换。 -
@Servy 我错过了。在这种情况下,仍然可以通过使用
as-cast 到可空类型来完成一次类型检查:var radius = obj as Radius?; return radius == null ? false : Equals(radius.Value);人们应该始终更喜欢as而不是is-followed-by-parenthetical-cast 为它只执行一种类型检查。 -
@cdhowie 可以执行的最快操作之一的速度提高了 30%。这在性能上的差异完全可以忽略不计,以至于在几乎任何应用程序中,即使提及它也不值得。如果类型本身可以为空,并且您想要可以为空的结果,则使用
as是有意义的,但感觉它在逻辑上不可以为空,您正在做的将其翻译回来的工作有效地消除了所获得的优势。这两种解决方案是相当的,差异几乎完全是主观偏好,仅此而已。
标签: c# .net exception boolean equality