zoukankan      html  css  js  c++  java
  • 浅析C#中的“==”和Equals

    对于“==”和Equals大多数网友都是这样总结的:

    1. “==” 是比较两个变量的值相等。
    2. Equals是比较两个变量是否指向同一个对象。

      如:这篇文章,并以这篇文章中的例子为例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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.

    1
    Console.WriteLine(a == b);         //true

      很明显,上面的两个字符串变量:a,b 是指向两个不同的对象,即它们在栈空间存储的内存地址也是不同的。但为毛它们就相等了呢?

     2.什么是运算符重载?

      运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。打个简单的比方:“+” 运算符,在“+” 两

      边全为数值类型的变量时,“+” 运算符表示数学上的“+” 意义。若“+” 运算符两边只要有一个为字符串类型,那么“+” 运算符就表示连接

      字符串的意义。这样的运算符重载实例有很多,那么这跟本文主题有毛关系?我想说的是,上面字符串变量:a , b 就是因为String类

      重载了运算符 “==”,看下列源代码:

    1
    2
    3
    4
    5
    6
    7
    8
    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方法,

      源代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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的重写

      还是上面例子:

    1
    2
    3
    4
    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方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    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,很多类中都重写了它,并真正达了在当前类型中所需的特定行为,即:多态。所以就不难解释上面:

    1
    2
    3
    4
    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。

  • 相关阅读:
    二分图最大匹配的K&#246;nig定理及其证明
    HDOJ 2389 Rain on your Parade
    HDOJ 1083 Courses
    HDOJ 2063 过山车
    POJ 1469 COURSES
    UESTC 1817 Complete Building the Houses
    POJ 3464 ACM Computer Factory
    POJ 1459 Power Network
    HDOJ 1532 Drainage Ditches
    HDU 1017 A Mathematical Curiosity
  • 原文地址:https://www.cnblogs.com/gc2013/p/4642024.html
Copyright © 2011-2022 走看看