==或.Equals()

为什么使用一个呢?

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

身份testing更快,所以你可以使用它,当不需要更昂贵的平等testing。 例如,比较null或空string。

为了提供不同的行为,比如Equals()身份testing,可能会重载其中的任何一个,但为了读取您的代码,请不要这么做。


指出如下:像StringDateTime一些types提供==运算符的重载,给它的平等语义。 所以确切的行为将取决于你正在比较的对象的types。


也可以看看:

@John Millikin:

指出如下:一些像DateTime这样的值types为==运算符提供了重载,它给了它相等的语义。 所以确切的行为将取决于您正在比较的对象的types。

详细说明:

DateTime是作为一个结构实现的。 所有结构都是System.ValueType的子项。

由于System.ValueType的孩子居住在堆栈上,因此没有引用指向堆的引用指针,因此无法进行引用检查,只能通过值来比较对象。

System.ValueType覆盖.Equals()和==来使用基于reflection的相等性检查,它使用reflection来比较每个字段的值。

因为reflection速度有点慢,所以如果你实现自己的结构体,重写.Equals()并添加你自己的值检查代码是很重要的,因为这会更快。 不要只调用base.Equals();

其他人几乎已经覆盖了,但我还有一个build议。 一次又一次,你会得到一个发誓的人(以及他所爱的人),那就是更高效/更好/最好的实践或者其他一些教条路线。 我不能说效率(当然,在某些情况下,我可以),但是我可以谈到一个大问题,这个问题会突然出现:.Equals需要一个对象来存在。 (听起来很愚蠢,但是却把人们抛弃了。)

你不能做到以下几点:

 StringBuilder sb = null; if (sb.Equals(null)) { // whatever } 

对于我,也许大多数人来说,看起来很明显,你会得到一个NullReferenceException。 然而,.Equals的支持者忘记了那个小小的事实。 当他们看到NullRefs开始popup时,有些甚至“抛出”(抱歉,无法抗拒)。

(在DailyWTF发布之前的几年 ,我确实和一个强制要求所有的平等检查都是等于而不是==的人一起工作,即使certificate他的不准确也没有帮助,我们只能做出违反所有其他规则的事情,没有从方法返回的参考,也没有任何属性是空的,最终得出结论。)

==一般是“身份”等于意思是“对象a实际上是与对象b完全相同的对象在内存中”。

equals()意味着对象在逻辑上相等(比如从商业angular度来看)。 因此,如果您要比较用户定义的类的实例,则通常需要使用和定义equals(),如果您希望像Hashtable一样正常工作。

如果你拥有名称为“Name”和“Address”的Person类,并且你想用这个Person作为一个包含更多关于它们的信息的Hashtable的键,你需要实现equals()(和hash),这样你可以创build一个Person的实例,并将其用作Hashtable中的键来获取信息。

单独使用==,你的新实例将不会相同。

根据MSDN :

在C#中,有两种不同的等式:引用相等(也称为身份)和值相等。 价值平等是平等普遍理解的含义:它意味着两个对象包含相同的值。 例如,两个值为2的整数具有值相等性。 引用相等意味着没有两个对象进行比较。 相反,有两个对象引用,它们都指向同一个对象。

默认情况下,运算符==通过确定两个引用是否指示相同的对象来testing引用相等。

该示例是因为DateTime类实现了IEquatable接口,该接口实现了“用于确定实例相等的types特定的方法”。 根据MSDN 。

另一件要考虑的事情是:==操作符可能无法调用,或者如果从另一种语言访问该对象,可能会有不同的含义。 通常,最好有一个可以按名称调用的替代方法。

Equals==都可以被重载,所以调用一个或另一个的确切结果会有所不同。 请注意, ==是在编译时确定的,所以虽然实际的实现可能会改变,但是使用哪个==在编译时是固定的,不像Equals可以使用基于左侧运行时types的不同实现。

例如, string执行==的相等testing。

还要注意两者的语义可能很复杂 。

最佳实践就是像这个例子一样实现平等。 请注意,您可以简化或排除所有这些,这取决于您计划如何使用您的类,并且该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 } } 

如果要expression比较的对象的内容应该是相等的。 对原始值使用==,或者如果您想检查被比较的对象是同一个对象。 对象==检查对象的地址指针是否相同。

我已经看到Object.ReferenceEquals()用于想知道两个引用是否引用同一个对象的情况

如果你真的反汇编(例如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为真(相等于数值types),第二次为真(相等于数值types),第三次为假(相等于参考types)。