首页 后端开发 C#.Net教程 Equals,ReferenceEquals,==的区别

Equals,ReferenceEquals,==的区别

Dec 16, 2016 am 09:53 AM
equals

在.net中有几种比较相等的方法

object的静态ReferenceEquals()

object的静态Equals()

object的示例Equals()

运算符==

下面介绍一下他们的区别和用法。

ReferenceEquals

ReferenceEquals用于比较引用类型的引用是是否指向同一个对象。它只能比较引用类型。当把值类型传给它的时候永远都会返回false,因为值类型作为参数的时候首先会装箱,经过装箱的值类型哪怕是指相等,但是也是两个不同的对象,所以变量是指向不同的对象,所以永远返回false。

int x = 10; 
int y = 10; 
bool b1 = object.ReferenceEquals(x,y); 
这里结果肯定是返回false,但是如果是比较引用类型,如果是两个引用指向同一个对象,则为true。

我们还是先定义实体类

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; 


调用代码

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); 
我们可以发现第一个返回false,第二个返回true。那么如果其中有一个对象为null,或者两个对象都为null呢?结果会为false,如果两个都为null呢?结果为true。他们不会引发异常。

实例Equals

实例Equals算是比较复杂的一个比较方法。实例Equals可以比较引用是否指向同一个对象,同时可以按值来比较对象。如果要按值比较对象,我们就需要重载Equals对象来实现我们的比较逻辑。同时Equals默认也支持比较值类型的相等。那么我们该怎么重载Equals来让对象具有值相等性的比较呢?

MSDN给我们列出了一些准则

除涉及浮点型的情况外,x.Equals(x) 都返回 true。

x.Equals(y) 返回与 y.Equals(x) 相同的值。

如果 x 和 y 都为 NaN,则 x.Equals(y) 返回 true。

当且仅当 x.Equals(z) 返回 true 时,(x.Equals(y) && y.Equals(z)) 才返回 true。

只要不修改 x 和 y 引用的对象,对 x.Equals(y) 的相继调用将返回相同的值。

x.Equals(nullNothingnullptrnull 引用(在 Visual Basic 中为 Nothing)) 返回 false。

我们来看看重写代码

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; 


调用代码

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)); 
我们可以看到结果,第一个为true,第二个为false。重载的时候不能出现异常。那么如果有一个类继承Person呢,我们又改如何比较派生类。

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中文网!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

c语言编译器怎么加下一格 c语言编译器怎么加下一格 Mar 03, 2025 pm 05:44 PM

本文解释了如何使用printf中的\ n逃脱序列在C中创建新线字符并列出函数。 它详细介绍了功能并提供了代码示例,以说明其用于输出中的线路断裂。

C语言中NULL的替代方案有哪些 C语言中NULL的替代方案有哪些 Mar 03, 2025 pm 05:37 PM

本文探讨了C中的无指针启用的挑战。它认为问题本身不是零,而是滥用。 本文详细介绍了预防退出的最佳实践,包括提出前检查,指针pitiberi

c语言编译器哪个好? c语言编译器哪个好? Mar 03, 2025 pm 05:39 PM

本文指导初学者选择C编译器。 它认为,海湾合作委员会由于其易用性,广泛的可用性和广泛的资源,最适合初学者。 但是,它也比较了海湾室,Clang,MSVC和TCC,突出了它们的差异

C语言中NULL在现代编程中还重要吗 C语言中NULL在现代编程中还重要吗 Mar 03, 2025 pm 05:35 PM

本文强调了NULL在现代C编程中的持续重要性。 尽管取得了进步,但NULL对于明确的指针管理仍然至关重要,从而通过标记没有有效的内存地址来防止细分故障。 最好的prac

c语言编译器网页版有哪些? c语言编译器网页版有哪些? Mar 03, 2025 pm 05:42 PM

本文回顾了初学者的在线C编译器,重点是易用性和调试功能。 在线GDB和REPL。 其他选项,例如Programiz和Compil

c语言编译器复制代码方法 c语言编译器复制代码方法 Mar 03, 2025 pm 05:43 PM

本文讨论了C IDE中的有效代码复制。 它强调,复制是IDE功能,而不是编译器功能,并且详细提高了效率的策略,包括使用IDE选择工具,代码折叠,搜索/替换,Templa

c语言在线编程网站 c语言编译器官方网站汇总 c语言在线编程网站 c语言编译器官方网站汇总 Mar 03, 2025 pm 05:41 PM

本文比较在线C编程平台,突出了诸如调试工具,IDE功能,标准合规性和内存/执行限制等功能的差异。 它认为“最佳”平台取决于用户需求

c语言编译器安装教程(电脑版) c语言编译器安装教程(电脑版) Mar 03, 2025 pm 05:41 PM

该教程通过在Windows,MacOS和Linux上安装C编译器来指导用户。 它详细介绍了流行编译器(Mingw,Visual Studio,Xcode,GCC)的安装,解释了环境变量配置,并提供故障排除步骤

See all articles