Home  >  Article  >  Backend Development  >  The difference between Equals, ReferenceEquals,==

The difference between Equals, ReferenceEquals,==

高洛峰
高洛峰Original
2016-12-16 09:53:011055browse

There are several methods of comparing equality in .net

object’s static ReferenceEquals()

object’s static Equals()

object’s example Equals()

operator==

The following introduces their differences and usage.

ReferenceEquals

ReferenceEquals is used to compare whether references of reference types point to the same object. It can only compare reference types. When a value type is passed to it, false will always be returned, because the value type is first boxed when used as a parameter. Even if the boxed value type refers to equality, it is still two different objects, so the variable points to different object, so it always returns false.

int x = 10;
int y = 10;
bool b1 = object.ReferenceEquals(x,y);
The result here will definitely return false, but if it is comparing reference types, if two references point to the same object , then it is true.

We still define the entity class first

public class Person
{
private int _personId;

public int PersonId
{
get { return _personId; }
set { _personId = value; }
}

private string _firstName;

public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}

private string _lastName;

public string LastName
{
get { return _lastName; }
set { _lastName = value ; }
}

public Person() { }

public Person(int personId, string firstName, string lastName)
{
this._personId = personId;
this._firstName = firstName;
this._lastName = lastName;
}
}
Calling code

Person person1 = new Person(1,"Edrick","Liu");
Person person2 = new Person(2, "Meci", "Luo");
Person person3 = person2;
bool br1= object.ReferenceEquals(person1,person2);
bool br2 = object.ReferenceEquals(person2, person3);
We can find that the first one returns false and the second one returns true. So what if one of the objects is null, or both objects are null? The result will be false, what if both are null? The result is true. They don't throw exceptions.

Instance Equals

Instance Equals is a relatively complex comparison method. Instances of Equals can compare whether references point to the same object and can compare objects by value. If we want to compare objects by value, we need to overload the Equals object to implement our comparison logic. At the same time, Equals also supports equality of comparison value types by default. So how do we overload Equals to allow objects to have value equality comparisons?

MSDN lists some guidelines for us

Except for cases involving floating point types, x.Equals(x) returns true.

x.Equals(y) returns the same value as y.Equals(x).

x.Equals(y) returns true if both x and y are NaN.

(x.Equals(y) && y.Equals(z)) returns true if and only if x.Equals(z) returns true.

Successive calls to x.Equals(y) will return the same value as long as the objects referenced by x and y are not modified.

x.Equals(nullNothingnullptrnull reference (Nothing in Visual Basic)) returns false.

Let’s take a look at the rewritten code

public class Person
{
private int _personId;

public int PersonId
{
get { return _personId; }
set { _personId = value; }
}

private string _firstName ;

public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}

private string _lastName;

public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}

public Person() { }

public Person(int personId, string firstName, string lastName)
{
this._personId = personId;
this._firstName = firstName;
this._lastName = lastName;
}

public override bool Equals(object obj)
{
if (obj != null && obj is Person)
{
Person p = obj as Person;

return (PersonId == p.PersonId) && (FirstName == p.FirstName) && (LastName == p.LastName);
}
else
{
return false;
}
}

public override int GetHashCode()
{
return base.GetHashCode()^PersonId;
}
}
Calling code

Person person1 = new Person(1,"Edrick","Liu");
Person person2 = new Person(2, "Meci", "Luo");
Person person3 = person2;
Person person4 = new Person(1, "Edrick", "Liu");

Console.WriteLine(person4.Equals(person1));
Console.WriteLine(person4.Equals(person2));
We can see As a result, the first one is true and the second one is false. No exceptions should occur during reloading. So if there is a class that inherits Person, how do we compare derived classes?

public class Student:Person 

private int _studentNumber;

public int StudentNumber 

get { return _studentNumber; } 
set { _studentNumber = value; } 
}

public Student() { }

public Student(int personId, string firstName, string lastName, int studentNumber) 

this.PersonId = personId; 
this.FirstName = firstName; 
this.LastName = lastName; 
this._studentNumber = studentNumber; 
}

public override bool Equals(object obj) 

if (obj != null && obj is Person) 

Student s = obj as Student; 
return base.Equals(obj)&&StudentNumber==s.StudentNumber; 

else 

return false; 

}

public override int GetHashCode() 

return base.GetHashCode()^StudentNumber; 


调用代码

Student s1 = new Student(1, "Edrick", "Liu", 1); 
Student s2 = new Student(2, "Meci", "Luo", 2); 
Student s3 = new Student(1, "Edrick", "Liu", 1);

Console.WriteLine(s1.Equals(s2)); 
Console.WriteLine(s1.Equals(s3)); 
我们只需要调用父类的Equals方法和比较派生类中的新值。

静态Equals

这个方法算是比较有趣的一个方法了。这个方法也是静态的,它能比较引用,能比较值类型。如果比较的类型重载了实例的Equals,那么它也能也比较对象的值。所以它返回true有三种情况。

1,引用指向同一个对象

2,比较两个null

3,重载了Equals的实例方法返回true

Student s1 = new Student(1, "Edrick", "Liu", 1); 
Student s2 = new Student(2, "Meci", "Luo", 2); 
Student s3 = new Student(1, "Edrick", "Liu", 1); 
Student s4 = s3;

Console.WriteLine(object.Equals(s1,s3)); 
Console.WriteLine(object.Equals(s4, s3)); 
这两个都为true,这里静态的Equals跟静态的EqualsReference有一个区别,静态的Equals如果有一个参数为null会抛出异常。

下面讨论一个有趣的现象,如果重载了Equals但是没有重载==运算符,会发生什么

Student s1 = new Student(1, "Edrick", "Liu", 1); 
Student s2 = new Student(2, "Meci", "Luo", 2); 
Student s3 = new Student(1, "Edrick", "Liu", 1); 
Student s4 = s3;

Console.WriteLine(s1==s3); 
Console.WriteLine(s3==s4); 
第一个为false,第二个为true。这显然不符合我们意图,所以重载了Equals必须重载==,同样重载了==也必须重载Equals。这样符合我们的意图,也能确保在使用集合的时候,代码能按照我们的意图工作。因为集合coll[0]==co[0]其实比较的是引用,但是如果我们的Equals比较的是对象的值那么最后代码还是不能按照我的期望的运行。

==运算符

==号运算符其实跟实例的Equals没有多大的区别,==是运算符,而Equals是方法。他们都可以重写。默认都能比较引用和比较值。关于==的重载可以参考运算符一文中的运算符重载。

总结他们的区别:

ReferenceEquals:静态方法,不能重写,只能比较引用,如果有一个参数为null会返回false,不会抛出异常,如果比较值类型,则始终返回false。

Equals:实例方法,默认可以比较引用也可以比较值,可以重写。可以按值比较对象。

静态Equals:静态方法,不能重写。如果没有重写Equals,比较引用,或者比较值。如果重载了Equals方法。比较引用,或者比较值,或者按重写的Equals比较,如果其中一个参数为null,抛出异常

==运算符:可以按引用比较,也可以按值比较。可以重写。是操作运算符。

最后需要的是,如果重载了Equals,则最好是重载GetHashCode,必须重载==运算符。




更多Equals,ReferenceEquals,==的区别相关文章请关注PHP中文网!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn