浅析C#中的“==”和Equals的示例代码
对于“==”和Equals大多数网友都是这样总结的:
“==” 是比较两个变量的值相等。
Equals是比较两个变量是否指向同一个对象。
如:这篇文章,并以这篇文章中的例子为例。
public class Person { public Person(string name) { this.Name = name; } public string Name { get; set; } } static void Main(string[] args) { string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); Console.WriteLine(a == b); //true Console.WriteLine(a.Equals(b)); //true object g = a; object h = b; Console.WriteLine(g == h); //false Console.WriteLine(g.Equals(h)); //true Person p1 = new Person("jia"); Person p2 = new Person("jia"); Console.WriteLine(p1 == p2); //false Console.WriteLine(p1.Equals(p2)); //false Person p3 = new Person("jia"); Person p4 = p3; Console.WriteLine(p3 == p4); //true Console.WriteLine(p3.Equals(p4)); //true Console.ReadKey(); }
假如上述结论正确,“==” 是比较两个变量值相等,那么下面这句代码就不应该为True.
Console.WriteLine(a == b); //true
很明显,上面的两个字符串变量:a,b 是指向两个不同的对象,即它们在栈空间存储的内存地址也是不同的。但为毛它们就相等了呢?
2.什么是运算符重载?
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。打个简单的比方:“+” 运算符,在“+” 两
边全为数值类型的变量时,“+” 运算符表示数学上的“+” 意义。若“+” 运算符两边只要有一个为字符串类型,那么“+” 运算符就表示连接
字符串的意义。这样的运算符重载实例有很多,那么这跟本文主题有毛关系?我想说的是,上面字符串变量:a , b 就是因为String类
重载了运算符 “==”,看下列源代码:
public static bool operator == (String a, String b) { return String.Equals(a, b); } public static bool operator != (String a, String b) { return !String.Equals(a, b); }
很明显String类中真的重载了“==”运算符,并且不止 “==” 还有 “!=” 哦。并且在重载运算符方法内部直接调用String类中的Equals方法,
源代码如下:
public static bool Equals(String a, String b) { if ((Object)a==(Object)b) { return true; } if ((Object)a==null || (Object)b==null) { return false; } if (a.Length != b.Length) return false; return EqualsHelper(a, b); }
由上可得:“==” 运算符并不一定是比较两个变量中存储的值是否相等,这要看当前运算符在当前这个类型中是否写有重载。
3.Equals的重写
还是上面例子:
string a = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); string b = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); Console.WriteLine(a == b); //true Console.WriteLine(a.Equals(b)); //true
由上可知:a ,b 为两个不同的对象。但Equals为True,则上述:“Equals是比较两个变量是否指向同一个对象“这一结论不成立。原因
看String类中的Equals方法:
public override bool Equals(Object obj) <br> { if (this == null) //this is necessary to guard against reverse-pinvokes and throw new NullReferenceException(); //other callers who do not use the callvirt instruction String str = obj as String; if (str == null) return false; if (Object.ReferenceEquals(this, obj)) return true; if (this.Length != str.Length) return false; return EqualsHelper(this, str); } public bool Equals(String value) <br> { if (this == null) //this is necessary to guard against reverse-pinvokes and throw new NullReferenceException(); //other callers who do not use the callvirt instruction if (value == null) return false; if (Object.ReferenceEquals(this, value)) return true; if (this.Length != value.Length) return false; return EqualsHelper(this, value); }
由上面可知String类中不仅重写了Object中的Equals还有自己的Equals方法,但是实现代码几乎是一样的。比较类型,内存地址,
实际值,从而获得最终的结果。所以Equals不一定就是单一的比较引用地址是否相同,更何况我们还可以重写和自定义。但是重写
Equals也有需要注意的地方,就是如果你需要用到HashMap,HashSet,Hashtable那么你也需要重写GetHashCode()。
4.为什么有了“==”还要有Equals?
中国有一句话:“任何事物的存在必然有他存在的道理和价值”,同理“==”和Equals也是一样。“==” 在引用类型中最基本的实现就是去比
较两对象的内存地址是否一致,一致则相等反之则不等。这样的实现很明显是从硬件角度去思考的,如果两个对象相等即为同一个对象,
那么它们在内存中的地址必然相等。但很多时候 “行为(方法)“ 是取决于我们去观察世界的角度。 如:String类型我们申明一个字符
串更在意的是字符串所具有的实际值,而不是在意两个对象在内存中是创建了一次还是两次(即内存地址是否相等),只要它们所具有的
实际值是相等的那么我们就认为它们是相等,这是从生活业务逻辑中去理解的而不是从机器角度上去理解的。当然上面声明相同的字符串
变量是创建一次还是两次我想:” 常量池(或字符串拘留池)“ 已经给了我们最好的解决方案。
5.“==”和Equals到底什么关系?
”==“ 运算符和Equals它们其实是互补关系。因为:”==“ 运算符主要实现形式是站在 ”计算机角度(或者说硬件角度)” 上去实现的,
而Equals是站在常用的业务场景或者是特定的业务场景下去实现的,二者没有什么必然的联系,是根据自己的业务需要选择不同方法而已。
所以Object里面的Equals是Visual,很多类中都重写了它,并真正达了在当前类型中所需的特定行为,即:多态。所以就不难解释上面:
object g = a; object h = b; Console.WriteLine(g == h); //false Console.WriteLine(g.Equals(h)); //true
因为Object中没有实现重载运算符:“==”,所以当前“==”的比较方式是比较两变量在栈空间存储的内存地址是否相同。而Equals则是
调用String类中的Equals,原因g变量在运行中它实际上指向一个字符串对象的,而当前的Object类型只是Visual studio和编译器的行为,即:还是多态。
最后任何东西都有它的规则:”==“和Equals也不例外,详细资料请点击:跳转至MSDN。
Atas ialah kandungan terperinci 浅析C#中的“==”和Equals的示例代码. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Panduan untuk Active Directory dengan C#. Di sini kita membincangkan pengenalan dan cara Active Directory berfungsi dalam C# bersama-sama dengan sintaks dan contoh.

Panduan untuk Penjana Nombor Rawak dalam C#. Di sini kita membincangkan cara Penjana Nombor Rawak berfungsi, konsep nombor pseudo-rawak dan selamat.

Panduan untuk Paparan Grid Data C#. Di sini kita membincangkan contoh cara paparan grid data boleh dimuatkan dan dieksport daripada pangkalan data SQL atau fail excel.

Panduan untuk Pensirian C#. Di sini kita membincangkan pengenalan, langkah-langkah objek siri C#, kerja, dan contoh masing-masing.

Panduan kepada Pengubahsuai Akses dalam C#. Kami telah membincangkan Pengenalan Jenis Pengubahsuai Akses dalam C# bersama-sama dengan contoh dan output.

Panduan Nombor Perdana dalam C#. Di sini kita membincangkan pengenalan dan contoh nombor perdana dalam c# bersama dengan pelaksanaan kod.

Panduan kepada Corak dalam C#. Di sini kita membincangkan pengenalan dan 3 jenis Corak teratas dalam C# bersama-sama dengan contoh dan pelaksanaan kodnya.

Panduan untuk Faktorial dalam C#. Di sini kita membincangkan pengenalan kepada faktorial dalam c# bersama-sama dengan contoh dan pelaksanaan kod yang berbeza.
