关于这两个东西的相似就没什么好说的了。他们在本质上有不同的。
总结起来是
==比较的是托管栈当中的内容,Equals()比较的是托管堆当中的内容。
要讲这个就得回归到C#中一个非常非常重要的内容当中,值类型与引用类型。其实第一次看值类型与引用类型的时候就理解这两个有什么差别和异同了。但是在之后的不断学习实践中有太多的内容又是和这个知识点有着密切关系。失常感觉这个简单的东西自己理解的还是不够深刻。
C#中的类型有两种一种叫值类型,另一种叫引用类型。
具体的分类也很好记忆
值类型包括 所有数字数据类型(int ,double等等)、Boolean、Char、Date、所有结构,即使其成员是引用类型(这个是结构与类的区别之一)、枚举
引用类型包括 String 所有数组,即使其元素是值类型 类类型 委托
其中烦人的是String类型,C#在很多地方会把Srting弄得和值类型很像。但这高级的货就是个引用类型
这只是分类,值类型和引用类型的差别在下面的图里
这个图是在丑陋(这个不是重点)
这里的栈和堆在DOTNET的条件下都是指托管栈和托管堆
栈的大小是有限制的,你开得太多会照成栈溢出。(在C/C++下得数组没法建的很大)
所以呢对于比较大坨的数据类型采用了图中的方式存放。把实体放在堆中,然后栈里面只放堆的地址。
应该不难理解,很多语言都是这样处理的。如果像C++保留指针结构的话应该更好理解图的内容
那比较小托的东西直接放在栈里面就好了,访问的时候速度还快一点。
小坨的就是值类型,大坨的就是引用类型。
虽然也可以把定义各类结构,然后再里面开一个巨大的东西把他弄得很大。不过没人会要那样吧。
现在说回来Equals()和==的事
==比较的是托管栈当中的内容,Equals()比较的是托管堆当中的内容。
写一些代码来实践一下
1: using System; 2: using System.Collections.Generic; 3: using System.Linq; 4: using System.Text; 5: 6: namespace TestEquals 7: { 8: class test 9: { 10: public int member; 11: public test(int member) 12: { 13: this.member = member; 14: } 15: } 16: class Program 17: { 18: static void Main(string[] args) 19: { 20: //值类型 21: int i1 = 10; 22: int i2 = 10; 23: Console.WriteLine("{0}", i1 == i2); 24: Console.WriteLine("{0}", i1.Equals(i2)); 25: 26: //引用类型 27: test t1 = new test(10); 28: test t2 = t1; 29: Console.WriteLine("{0}", t1 == t2); 30: Console.WriteLine("{0}", t1.Equals(t2)); 31: 32: test t3 = new test(10); 33: test t4 = new test(10); 34: Console.WriteLine("{0}", t3 == t4); 35: Console.WriteLine("{0}", t3.Equals(t4)); 36: object o1 = 10; 37: object o2 = 10; 38: Console.WriteLine("{0}", o1 == o2); 39: Console.WriteLine("{0}", o1.Equals(o2)); 40: 41: Console.ReadKey(); 42: } 43: } 44: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }输出结果是第一对是值类型,直接存放在栈中,内容又是一样的。所以两个都是T
第二对
27行做了两件事 一个是new了一个test 类型的对象放在堆里面 另一个是定义了一下test 类型的引用t1,t1是存放在栈中,t1的内容是一个堆的地址.那个地址就是new出来的首地址
28行定义了t2,并把t1的内容(那个堆的地址)赋给t2
所以t1,t2在栈的位置是不同的,但是他们的栈的内容是相同的,栈内容指向的堆自然也是相同的
第三对 两个引用 new了两个东西。所以都是F
第四对 这个是对诡异的一对了。o1 o2 是类类型的对象 所以属于引用类型。然后又直接用数值复制。我用数值给引用复制。o1,o2 栈中的东西是不一样的,但是堆中的东西又是一样的。
我避开了Sring类型 因为它重载了Equals().
写到这里,其实感觉这篇文章有点无意义。不过因为值类型和引用类型的东西,我还是决定发一下。
下面有一些值得参考的文章
http://blog.sina.com.cn/s/blog_61090e890100eb6b.html http://www.cnblogs.com/jiahaipeng/archive/2008/04/11/1146316.html http://msdn.microsoft.com/zh-cn/library/7h9bszxx%28VS.85%29.aspx http://msdn.microsoft.com/zh-cn/library/ms173147%28v=vs.90%29.aspx
