为什么要使用其中一个?
答案 0 :(得分:56)
==是身份测试。如果被测试的两个对象实际上是同一个对象,它将返回true。 Equals()
执行相等测试,如果两个对象认为自己相等,则返回true。
身份测试更快,因此您可以在不需要更昂贵的相等测试时使用它。例如,与null
或空字符串进行比较。
可以重载这些中的任何一个以提供不同的行为 - 例如Equals()
的身份测试 - 但是为了任何人阅读您的代码,请不要。
下面指出:某些类型如String
或DateTime
为==
运算符提供重载,赋予它相等的语义。因此,确切的行为将取决于您要比较的对象的类型。
另见:
答案 1 :(得分:20)
@John Millikin:
下面指出:一些像DateTime这样的值类型为==运算符>提供重载,赋予它相等的语义。因此,确切的行为将取决于您要比较的>对象的类型。
详细说明:
DateTime作为结构实现。所有结构都是System.ValueType的子代。
由于System.ValueType的子节点存在于堆栈中,因此没有指向堆的引用指针,因此无法进行引用检查,您必须仅按值比较对象。
System.ValueType重写.Equals()和==使用基于反射的相等性检查,它使用反射来比较每个字段的值。
因为反射有点慢,如果你实现自己的结构,重要的是覆盖.Equals()并添加你自己的值检查代码,因为这会更快。不要只调用base.Equals();
答案 2 :(得分:15)
其他人几乎已经覆盖了你,但我还有一个建议。每隔一段时间,你就会得到一个发誓一生(以及他所爱的人)的人.Equals
更有效/更好/最佳实践或其他一些教条。我不能说效率(好吧,好吧,在某些情况下我可以),但是我可以谈到一个重大问题:.Equals
需要一个对象存在。 (听起来很愚蠢,但却让人们失望。)
您无法执行以下操作:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
对我来说,也许是大多数人,你会得到一个NullReferenceException
。然而,.Equals
的支持者忘记了那个小事实。当他们看到NullRefs开始弹出时,有些甚至被“抛弃”(抱歉,无法抗拒)。
(在DailyWTF发布之前的几年,我确实与强制执行的人合作,所有等同性检查都是.Equals
而不是==
。甚至证明他的不准确没有帮助。我们只是确定要打破他所有的其他规则,以便从方法和属性返回的引用都不会为空,并且它最终会成功。)
答案 3 :(得分:6)
==通常是“身份”等于意思是“对象a实际上是内存中与对象b完全相同的对象”。
equals()表示对象在逻辑上相等(例如,从业务角度来看)。因此,如果要比较用户定义类的实例,如果希望Hashtable之类的东西能够正常工作,通常需要使用和定义equals()。
如果你有一个具有属性“Name”和“Address”的谚语Person类,并且你想使用这个Person作为包含更多关于它们的信息的Hashtable的键,你需要实现equals()(和hash)这样您就可以创建Person的实例并将其用作Hashtable的键以获取信息。
单独使用==,您的新实例将不相同。
答案 4 :(得分:3)
Equals
和==
都可以重载,因此调用其中一个或另一个的确切结果会有所不同。请注意==
是在编译时确定的,因此虽然实际实现可能会发生变化,但==
的使用在编译时是固定的,与Equals
不同,string
可以使用基于运行时左侧的类型。
例如==
执行struct
的等式测试。
另请注意,两者的语义可以是complex。
最佳做法是像这个例子那样实现平等。请注意,您可以简化或排除所有这些,具体取决于您计划如何使用您的课程,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
}
}
已经获得了大部分内容。
{{1}}
答案 5 :(得分:2)
根据MSDN:
在C#中,有两种不同的相等:引用相等(也称为标识)和值相等。值相等是通常理解的相等含义:它意味着两个对象包含相同的值。例如,值为2的两个整数具有值相等性。引用相等意味着没有两个对象可供比较。相反,有两个对象引用,它们都引用同一个对象。
...
默认情况下,operator ==通过确定两个引用是否指示同一对象来测试引用相等性。
答案 6 :(得分:2)
该示例是因为DateTime类实现了IEquatable接口,该接口实现了“特定于类型的方法来确定实例的相等性”。根据{{3}}。
答案 7 :(得分:2)
要考虑的另一件事:如果从另一种语言访问对象,则==运算符可能无法调用或可能具有不同的含义。通常,最好有一个可以通过名称调用的替代方案。
答案 8 :(得分:1)
使用equals如果要表达对象的内容,则应该相等。 use ==表示原始值,或者如果要检查被比较的对象是否是同一个对象。对于objects ==检查对象的地址指针是否相同。
答案 9 :(得分:1)
我见过Object.ReferenceEquals()用于想知道两个引用是否引用同一个对象的情况
答案 10 :(得分:1)
在大多数情况下,它们是相同的,因此为了清晰起见,您应该使用==。根据Microsoft框架设计指南:
" DO 确保Object.Equals和相等运算符具有完全相同的语义和类似的性能特征。" https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators
但有时,有人会覆盖Object.Equals而不提供相等的运算符。在这种情况下,您应该使用Equals来测试值的相等性,使用Object.ReferenceEquals来测试引用相等性。
答案 11 :(得分:0)
如果您对Object进行反汇编(例如通过dotPeek),那么
public virtual bool Equals(Object obj)
描述为:
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
所以,取决于类型。 例如:
Object o1 = "vvv";
Object o2 = "vvv";
bool b = o1.Equals(o2);
o1 = 555;
o2 = 555;
b = o1.Equals(o2);
o1 = new List<int> { 1, 2, 3 };
o2 = new List<int> { 1, 2, 3 };
b = o1.Equals(o2);
第一次b为真(对值类型执行相等),第二次b为真(对值类型执行相等),第三次b为假(对引用类型执行相等)。