为什么要选择其中一个而不选择另一个?
==
是身份测试,如果正在测试的两个对象实际上是同一个对象,则返回true。Equals()
执行相等性测试,如果两个对象认为自己相等,则返回true。
身份测试更快,因此您可以在不需要更昂贵的相等性测试时使用它。例如,与null
或空字符串进行比较。
可能会重载其中任何一个以提供不同的行为-例如,对于Equals()
进行身份测试-但出于任何人阅读您的代码的缘故,请不要这样做。
如下所指出:某些类型(如String
或DateTime
)提供了==
运算符的重载,使其具有相等语义。因此,确切的行为取决于您要比较的对象的类型。
另请参见:
@John Millikin:
如下所指出:一些值类型,如DateTime,提供了重载==运算符以实现相等的语义。因此,确切的行为将取决于您正在比较的对象的类型。
更进一步说:
DateTime是一个结构体实现。所有结构体都是System.ValueType的子类。
由于System.ValueType的子类存储在堆栈上,没有引用指向堆,因此无法进行引用检查,只能按值进行比较。
System.ValueType重写.Equals()和==方法使用反射来进行相等性检查,它使用反射来比较每个字段的值。
由于反射有点慢,如果您自己实现了一个结构体,重要的是要重写.Equals()并添加自己的值检查代码,因为这样会更快。不要只调用base.Equals();
其他人已经基本上为您提供了答案,但我还有一个建议。偶尔会有人发誓要以他的生命(和他所爱的人的生命)来证明.Equals
更高效/更好/最佳实践或其他教条主义观点。我不能说它是否高效(好吧,在某些情况下我可以),但我可以说一个大问题会出现:.Equals
需要一个对象存在。(听起来很愚蠢,但它会让人感到困惑。)
你不能这样做:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
对我和大部分人来说,似乎很明显会出现NullReferenceException
。然而,支持使用.Equals
的人却忽略了这个小事实。当他们看到空引用开始弹出时,有些人甚至会被“抛”开(抱歉,我忍不住)。
(在DailyWTF发帖几年前,我曾经和一个人一起工作,他坚持要求所有的相等检查都使用.Equals
而不是==
。即使证明了他的错误也没用。我们只是确保打破了他的所有其他规则,以便从方法或属性返回的任何引用都不是null,并且最终解决了问题)。
if (sb?.Equals(null) ?? true)
,但是那肯定比 if (sb == null)
更加笨拙和不易读。 - saluceObject.Equals(Object obj)
的官方建议明确提到,对于 obj
的 null
值应显式返回 false
。它还指出实现不应抛出异常。尽管如此,您无法保证每个人都遵循这个明智的建议!https://learn.microsoft.com/en-us/dotnet/api/system.object.equals - jmlaneobject.Equals(object, object)
,它可以接受空对象。例如:if (object.Equals(sb, null) {..}
,或者简写为if (Equals(sb, null)) {..}
。 - user11909“==” 通常表示“身份”相等,即“对象 a 实际上与对象 b 在内存中完全相同”。
“equals()” 表示对象在逻辑上相等(例如从业务角度)。因此,如果要比较用户定义类的实例,则通常需要使用并定义 equals() 方法,如果您想让像 Hashtable 这样的东西正常工作。
例如,如果您有一个带有属性“姓名”和“地址”的 Person 类,并且想将此 Person 用作 Hashtable 中包含更多信息的键,那么您需要实现 equals() 和 hash(),以便创建 Person 的实例并将其用作 Hashtable 的键来获取信息。
仅使用 “==”,您的新实例将不相同。
...
默认情况下,操作符 == 通过确定两个引用是否指向同一个对象来测试引用相等性。
Equals
和==
都可以被重载,因此调用其中一个的确切结果会有所不同。请注意,==
在编译时确定,因此实际实现可能会改变,但使用哪个==
在编译时是固定的,而Equals
则根据左边的运行时类型可能使用不同的实现。
例如,string
执行==
的等式测试。
还要注意,两者的语义可能很复杂。
最佳实践是像这个例子一样实现相等性。请注意,您可以根据计划如何使用类来简化或排除所有这些内容,并且struct
已经获得了大部分内容。
class ClassName
{
public bool Equals(ClassName other)
{
if (other == null)
{
return false;
}
else
{
//Do your equality test here.
}
}
public override bool Equals(object obj)
{
ClassName other = obj as null; //Null and non-ClassName objects will both become null
if (obj == null)
{
return false;
}
else
{
return Equals(other);
}
}
public bool operator ==(ClassName left, ClassName right)
{
if (left == null)
{
return right == null;
}
else
{
return left.Equals(right);
}
}
public bool operator !=(ClassName left, ClassName right)
{
if (left == null)
{
return right != null;
}
else
{
return !left.Equals(right);
}
}
public override int GetHashCode()
{
//Return something useful here, typically all members shifted or XORed together works
}
}
另一个需要考虑的因素是:如果您从另一种语言访问对象,则==运算符可能不可调用或具有不同的含义。通常最好使用可通过名称调用的替代方法。
如果您想表达所比较的对象的内容相等,请使用equals。对于原始值或者如果您想检查被比较的对象是否是同一个对象,请使用==。对于对象,== 检查对象的地址指针是否相同。
Equals
和==
都可以被重载,因此调用它们的确切结果会有所不同。例如,string
使用==
进行相等性测试。还要注意,它们的语义可能是复杂的。 - Guvante