我在看MSDN上的IEquatable.Equals。具体来说,这两个部分的部分等于操作符:
public override bool Equals(Object obj)
{
if (obj == null)
return false;
Person personObj = obj as Person;
if (personObj == null)
return false;
else
return Equals(personObj);
}
public static bool operator == (Person person1, Person person2)
{
if (((object)person1) == null || ((object)person2) == null)
return Object.Equals(person1, person2);
return person1.Equals(person2);
}我一直在纠结的是:
if (((object)person1) == null || ((object)person2) == null)
return Object.Equals(person1, person2);if ( person1 == null || person2 == null )?false在我看来,
if (((object)person1) == null || ((object)person2) == null)
return Object.Equals(person1, person2);只是一种复杂的写作方式:
if ( person1 == null || person2 == null )
return false;还是我漏掉了什么?
发布于 2016-01-19 03:43:58
为什么要在检查对象是否为空之前将其转换为对象?
您处于==的重载状态,因此如果不进行转换,就会调用该重载,并且会出现带有堆栈溢出的无限递归(或者更糟的是,如果它成功地优化了尾调用,则会有一个无限循环)。你需要确保你把object的==打给你而不是你自己。
为什么打电话给Object.Equals?当然,如果其中一个项是空的,那么它就是
false?
如果它们都为,则为空,则为真。
因此,这是有道理的。不过我不推荐。仅仅完成空检查本身就更简单了:
if ((object)person1 == null)
return (object)person2 == null;
if ((object)person2 == null)
return false; // we already know person1 isn't null
// Follow with rest of logic.我们可以在这里做几种不同的模式。我们也可以:
if ((object)person1 == null && (object)person2 == null) return true;
if ((object)person1 == null || (object)person2 == null) return false;
// Follow with rest of logic.到目前为止,仅仅是一个额外的比较,就有很多不同之处。仍然检查一个引用是否与另一个引用相同(包括检查它是否为空)是很便宜的。让我们把树枝去掉,这样:
if ((object)person1 == null & (object)person2 == null) return true;
if ((object)person1 == null | (object)person2 == null) return false;
// Follow with rest of logic.在每一行中,潜在不必要的检查的额外成本很可能低于是否执行分支的成本,因此这是一次胜利。
但是现在考虑一下,第一行是检查它们是否都为空。实际上,这只是它们的一个子集,它们都是同一个实例。让我们来检查一下:
if ((object)person1 == (object)person2) return true;
if ((object)person1 == null | (object)person2 == null) return false;
// Follow with rest of logic.现在,除了处理它们都为null的情况之外,我还处理了它们都是同一个对象的情况。由于它具有相同的引用-标识检查,所以这几乎不会增加方法的成本,但是如果我们必须检查很多东西以确保两项相等(考虑检查两个非常大的字符串,并且在检查每个字符或排序单位后才知道它们是相同的),那么它就给了我们一个快速的true,它可能是非常慢的true。
现在,让我们考虑一下,Equals()是我们拥有大部分逻辑的地方。如果我们应用上述方法,我们可以在以下两种方法之间进行选择:
public static bool operator == (Person person1, Person person2)
{
if ((object)person1 == (object)person2)
return true;
if ((object)person1 == null | (object)person2 == null)
return false;
return person1.Equals(person2);
}和
public static bool operator == (Person person1, Person person2)
{
if ((object)person1 == (object)person2)
return true;
return ((object)person1 != null && person1.Equals(person2);
}后者取决于这样一个事实,即person1.Equals(person2)将检查person2是否为空。当person2为null时,前者(因为它避免了分支)可能是一次轻微的胜利,而后者则可能是一次轻微的胜利,而且更加简洁。我一般会选后者。
因此,在引用的示例中使用object.Equals()是有效的,但这不是我推荐的方法。
顺便说一句,他们对object.Equals()建议的覆盖,我完全不建议:
public override bool Equals(Object obj)
{
if (obj == null)
return false;
Person personObj = obj as Person;
if (personObj == null)
return false;
else
return Equals(personObj);
}如果您删除了第一个空检查,那么第二个检查仍然会捕获该情况。
如果您删除了第二个null检查,那么对Equals()的调用(接受Person的重载调用)将捕获它。
因此,它应该是:
public override bool Equals(object obj)
{
return Equals(obj as Person);
}该模式将用作实现Equals(object)的任何类的IEquatable<T>覆盖(在某些情况下,您可能希望将对象视为不同类型的对象之一,但即使是这样做,这些对象也是罕见的,而且常常是错误的,因此应该被认为是非常特殊的情况)。对于任何您可以使用的结构:
public override bool Equals(object obj)
{
return obj is TheStructType && Equals((TheStructType)obj);
}https://stackoverflow.com/questions/34867958
复制相似问题