C#的==和equals区别详解(你想知道都在这里)

学习过程中遇到了==和Equals的区别问题,在网上找了许多资料,看了许多博客。有些的写的不全面,有些的写的不清晰,没有代码实例,于是我就写下这篇总结,供大家学习,也供自己日后回顾。

 

一般情况下,equals函数是比较两对象的值是否相同

                     ==是比较两对象的引用,引用地址是否相同

但是C#里面不同的数据类型,会发生不同的现象

小结:大概分为五类

1 对象是值类型,==和equals等效,都是比较两对象的值

2 对象是除string外的非匿名类引用类型,==和equals等效,比较的都是对象的引用

3 对象是string的引用,==和equals等效,比较的是对象的值

4 对象是匿名类,==比较对象的引用,equals比较对象的值

5 对象涉及装箱拆箱操作,==比较的是对象的引用,equals和装箱之前的对象的equals方法一样

原因在于,这个Equals不是object基类中那个与==一样的方法

调用的实际上是装箱之前对象的equals

例子1:值类型

static void Main(string[] args)
        {
            int i1 = 10;
            int i2 = 10;
            double d1 = 3.14;
            double d2 = 3.14;
            Console.WriteLine("值类型==和Equals方法测试");

            Console.WriteLine("int测试");
            Console.WriteLine("i1 equals i2  "+i1.Equals(i2));//True
            Console.WriteLine("i1==i2  "+(i1 == i2));//True

            Console.WriteLine("double测试");
            Console.WriteLine("d1 equals d2  " + d1.Equals(d2));//True
            Console.WriteLine("d1==d2  " + (d1 == d2));//True

            Console.Read();       
 	}	

例子二:非匿名类引用类型

 public class Friend
    {
        public string Name { get; set; }

        public string Sex { get; set; }

        public int Age { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("非匿名类引用类型==和Equals方法测试");

            Friend f1 = new Friend { Name = "zhangsan", Age = 20, Sex = "male" };
            Friend f2 = new Friend { Name = "zhangsan", Age = 20, Sex = "male" };

            Console.WriteLine("f1==f2  "+(f1 == f2));//False
            Console.WriteLine("f1 equals f2 "+f1.Equals(f2));//False

            Console.Read();
        }
}

例子三:string类型

static void Main(string[] args)
        {
            Console.WriteLine("String类型==和Equals方法测试");
              StringBuilder strb = new StringBuilder("hello");  
              string str1, str2;  
              str1 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });  
              str2 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });  
              string str3 = "hello";  
              string str4 = "hello";  

              Console.WriteLine("str1 equals str2  "+str1.Equals(str2));  //True
              Console.WriteLine("str1==str2  " + (str1 == str2));         //True

            Console.WriteLine("str3 equals str4  "+str3.Equals(str4));  //True
            Console.WriteLine("str1==str2  " + (str1 == str2));//True

            Console.WriteLine("str1 equals str3  "+str1.Equals(str3));  //True
            Console.WriteLine("str1==str2  " + (str1 == str2));//True

            Console.WriteLine(str1.Equals(strb.ToString()));  //True
            Console.WriteLine(str1 == strb.ToString());//True

            Console.Read();

        }

微软重写了string的Equals()方法,使得这个方法比对的是string的字符串内容,同时也重载了==运算符,使得string在进行==比对时,得到的结果与Equals()相同,即比对字符串内容(这点区别于Java)

不管字符串的创建方式是

声明 string str3 = "hello";  

还是使用new创建对象str1 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });  

两个都等效,比较的是对象的值

 

例子四:匿名类类型

static void Main(string[] args)
        {
            Console.WriteLine("匿名类==和Equals方法测试");
            var vClass1 = new { Name = "abc", Age = 20 };
            var vClass2 = new { Name = "abc", Age = 20 };
            var vClass3 = new { Name = "abd", Age = 21 };
            Console.WriteLine("v1 equals v2  "+vClass1.Equals(vClass2));           //true  
            Console.WriteLine("v1 equals v3  " + vClass1.Equals(vClass3));          //false  
            Console.WriteLine("v1==v2  "+(vClass1 == vClass2));                  //false  
            Console.WriteLine("v1==v3  "+(vClass1 == vClass3));                  //false 

            Console.Read();

        }

例子五:装箱操作

 static void Main(string[] args)
        {
            Console.WriteLine("装箱操作==和Equals方法测试");
            string a = "Hello";
            string b = "Hello";
            Console.WriteLine("String类测试(申明对象方式)");
            Console.WriteLine("a==b  "+(a == b)); //结果为true
            Console.WriteLine("a equals b  "+a.Equals(b));//结果为true
            object oa = a;
            object ob= b;
            Console.WriteLine("String类装箱后测试");
            Console.WriteLine("oa==ob  "+(oa==ob));//结果为true
            Console.WriteLine("oa equals ob  "+oa.Equals(ob));//结果为true

            Console.WriteLine();

            string str1 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
            string str2 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' });
            Console.WriteLine("String类测试(New对象方式)");
            Console.WriteLine("str1==str2  " + (str1 == str2)); //结果为true
            Console.WriteLine("str1 equstr1ls str2  " + str1.Equals(str2));//结果为true
            object ostr1 = str1;
            object ostr2 = str2;
            Console.WriteLine("String类装箱后测试");
            Console.WriteLine("ostr1==ostr2  " + (ostr1 == ostr2));//结果为false
            Console.WriteLine("ostr1 equstr1ls ostr2  " + ostr1.Equals(ostr2));//结果为true

            Console.WriteLine();
            Console.WriteLine("ReferenceEquals(a,b)  "+ReferenceEquals(a, b));//结果为true
            Console.WriteLine("ReferenceEquals(str1,str2)  "+ReferenceEquals(str1, str2));//结果为false
            //使用ReferenceEquals比较两对象的引用是否相等
            Console.WriteLine();
            Console.WriteLine("ReferenceEquals(oa,ob)  " + ReferenceEquals(oa, ob));//结果为true
            Console.WriteLine("ReferenceEquals(ostr1,ostr2)  " + ReferenceEquals(ostr1, ostr2));//结果为false

            Console.WriteLine();

            int x = 10;
            int y = 10;
            Console.WriteLine("Int测试");
            Console.WriteLine("x==y  " + (x == y));//结果为true
            Console.WriteLine("x equals y  " + x.Equals(y));//结果为true
            object ox = x;
            object oy = y;
            Console.WriteLine("Int装箱后测试");
            Console.WriteLine("ox==ob  " + (ox == oy));//结果为false
            Console.WriteLine("ox equals ob  " + ox.Equals(oy));//结果为true


            Console.Read();
        }

这个例子中,通过string类两种不同的创建方式,对==和equals有了更深刻的理解

String申明对象的方式,当两个字符串相同时,实际上系统只会生成一个字符串,两个变量指向的同一个地方。

String使用New方式创建对象,实际上是创建了两个对象,地址不同

 

由于string类的==和equals方法是等效的,都是比较两个对象的值。

所以看不出区别

我们使用ReferenceEquals方法比较两对象的地址,可以看出问题

Console.WriteLine("ReferenceEquals(a,b)  "+ReferenceEquals(a, b));//结果为true

Console.WriteLine("ReferenceEquals(str1,str2)  "+ReferenceEquals(str1, str2));//结果为false           

//使用ReferenceEquals比较两对象的引用是否相等

 

C#装箱拆箱问题,由于知识有限,暂不能肯定

以下结论均为个人猜测,可能存在问题 ,有问题请指出

Console.WriteLine("oa==ob  "+(oa==ob));//结果为true

Console.WriteLine("ostr1==ostr2  " + (ostr1 == ostr2));//结果为false

Console.WriteLine("ReferenceEquals(oa,ob)  " + ReferenceEquals(oa, ob));//结果为true

Console.WriteLine("ReferenceEquals(ostr1,ostr2)  " + ReferenceEquals(ostr1, ostr2));//结果为false

那么oa和ob的地址也是一样的,oa和ob都指向同一个地方

而ostr1和ostr2指向的两个不同的地方

全部评论

相关推荐

不愿透露姓名的神秘牛友
10-12 10:48
已编辑
秋招之苟:邻居家老哥19届双2硕大厂开发offer拿遍了,前几天向他请教秋招,他给我看他当年的简历,0实习实验室项目技术栈跟开发基本不沾边😂,我跟他说这个放在现在中厂简历都过不了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务