==或.Equals()

时间:2008-09-27 21:36:37

标签: c#

为什么要使用其中一个?

12 个答案:

答案 0 :(得分:56)

==是身份测试。如果被测试的两个对象实际上是同一个对象,它将返回true。 Equals()执行相等测试,如果两个对象认为自己相等,则返回true。

身份测试更快,因此您可以在不需要更昂贵的相等测试时使用它。例如,与null或空字符串进行比较。

可以重载这些中的任何一个以提供不同的行为 - 例如Equals()的身份测试 - 但是为了任何人阅读您的代码,请不要。


下面指出:某些类型如StringDateTime==运算符提供重载,赋予它相等的语义。因此,确切的行为将取决于您要比较的对象的类型。


另见:

答案 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为假(对引用类型执行相等)。