当前位置 博文首页 > 陈大宝:C#基础之==(双等于号)与equals()区别

    陈大宝:C#基础之==(双等于号)与equals()区别

    作者:陈大宝 时间:2021-05-25 18:21

    C#Equals和= =比较

    这两种方式也是大家在日常编码工作当中用的比较多的判断方式、之前在使用的时候也没太关注两者在比较不同类型的时候存在哪些区别、

    今天就和大家一起深入了解一下其中区别

    一、值类型比较判断

    对于值类型来说  两者之间比较的都是”内容”是否相同,即值类型中的数值是否一样,很显然此时两者是划等号的,代码展示如下:

     #region 值类型判断
     int i = 10;
     int j = 10;
     Console.WriteLine($"双等于号判断结果为:{(i == j)}");
     Console.WriteLine($"Equals判断结果为:{i.Equals(j)}");
    
     #endregion

    控制台输出:

     

     由此判断在值类型中使用int类型为例,其中等于号与Equals二者的判断不存在区别、都是比较其中的数值内容、那么引用类型存在区别吗一起来看一看?

    一、引用类型比较判断

     对于引用类型来说,等号(==)比较的是两个变量的”引用” 是否一样,即是引用的”地址”是否相同。而对于equals来说仍然比较的是变量的  ”内容” 是否一样

    1、引用类型中字符串比较(String)

     #region 引用类型中String比较
     Console.WriteLine("----------------我是分割线-----------------------");
     string str1 = "abd";
     string str2 = "abd";
     Console.WriteLine($"双等于号判断结果为:{(str1 == str2)}");
     Console.WriteLine($"Equals判断结果为:{str1.Equals(str2)}");
     #endregion
    

    控制台输出:

      那么问题来了?Equals是比较其中的数值相等返回True我可以理解、那么字符串中双等于号是比较二者之间的引用、很显然str1变量与str2变量是不同的引用

    为什么返回的结果怎么还是True呢?实际的原因是什么呢?一起来看一看

    //
    // 摘要:
    //     Determines whether two specified strings have the same value.
    //
    // 参数:
    //   a:
    //     The first string to compare, or null.
    //
    //   b:
    //     The second string to compare, or null.
    //
    // 返回结果:
    //     true if the value of a is the same as the value of b; otherwise, false.
    public static bool operator ==(String? a, String? b);
    
    
    //
    // 摘要:
    //     Determines whether this instance and another specified System.String object have
    //     the same value.
    //
    // 参数:
    //   value:
    //     The string to compare to this instance.
    //
    // 返回结果:
    //     true if the value of the value parameter is the same as the value of this instance;
    //     otherwise, false. If value is null, the method returns false.
    public bool Equals(String? value);

    不管是==、还是Equals也好都是微软提供的public sealed class String密封类下面的提供的方法、看到此时还看不出其中的缘由、那么直接上反编译工具看一看究竟。

     

      点击str3==str2中的等于号继续查看、发现反编译中查看这个方法的源码返回了Equals这个方法、这样一看就大致清楚了、string类型中微软的开发

    人员对这个==进行的重写。

     

     

     

     以上是Equals与==反编译源码所以这也就是当我们在比较String类型时、不同的引用、数值一样、Equals与==返回的结果一致、相同、所以在进行String类型判断

    这两个方法内部本质是相同的、当然String类型是一个特例。

    2、引用类型中自定义类型比较

     #region 引用类型中自定义类型t比较
     Console.WriteLine("----------------我是分割线-----------------------");
     Car car1 = new Car()
     {
         Age = 4,
         Color = "Green"
     };
     Car car2 = new Car()
     {
         Age = 4,
         Color = "Green"
     };
    
     Console.WriteLine($"双等于号判断结果为:{(car1 == car2)}");
     Console.WriteLine($"Equals判断结果为:{car1.Equals(car2)}");
    

    控制台输出:

     二者都是输出False、由于不同的引用实例、所以引用的地址也是不同的、即使数值相同==也会返回False、可能有人会产生疑问,car1 和car2的内容是相同的啊,为什么他俩的比较结果却是为false呢?。原因就在于在Equals是Object中的一个虚方法,而Car类中没有对它进行重写,因此此时调用的仍是父类中的Equals方法。但是父类是无法知道你都有哪些成员字段的,因此返回的是false。要想让他能够比较两个变量的内容是否相同,那就应该重写Equals方法

    2、重写Equals并测试

    新建类并测试代码如下:

      public class TwoDPoint : System.Object
        {
            public readonly int x, y;
    
            public TwoDPoint(int x, int y) 
            {
                this.x = x;
                this.y = y;
            }
    
            public override bool Equals(System.Object obj)
            {
                if (obj == null)
                {
                    return false;
                }
    
                TwoDPoint p = obj as TwoDPoint;
                if ((System.Object)p == null)
                {
                    return false;
                }
                return (x == p.x) && (y == p.y);
            }
    
            public bool Equals(TwoDPoint p)
            {
                if ((object)p == null)
                {
                    return false;
                }
    
                return (x == p.x) && (y == p.y);
            }
    
            public override int GetHashCode()
            {
                return x ^ y;
            }
    
    
        }

    上端调用测试

      #region 引用类型中自定义类型t比较
      Console.WriteLine("----------------我是分割线-----------------------");
    
      TwoDPoint twoDPoint1 = new TwoDPoint(4, 8);
      TwoDPoint twoDPoint2 = new TwoDPoint(4, 8);
    
      Console.WriteLine($"双等于号判断结果为:{(twoDPoint1 == twoDPoint2)}");
      Console.WriteLine($"Equals重写后判断结果为:{twoDPoint1.Equals(twoDPoint2)}");
      #endregion

    控制台输出:

     

     结果显示Equals重写后返回True、==引用的地址不同、所以还是返回False、由此可以证明重写后验证成功。

    总结:Equals比较的永远是变量的内容是否相同,而= =比较的则是引用地址是否相同(前提:此种类型内部没有对Equals 或= = 进行重写操作,否则输出可能会有不同)

    string 类型是个特例,因为他的内部对这两个都进行了重写、以上本人亲测有效、有什么需要改善的欢迎大家提出来、我加以改正。有时候短短几行代码其实要细细研究还是会细思极恐

    总而言之还是微软的大佬的给我们封装好了、我们拿来用就可以、但是在用的同时确实也需要有时间研究一下其中原理、其实可以多使用反编译工具研究一下其中代码原理、我这里使用的是

    ILSPY

     

    bk