C65507;# Equal function and operator'='(originally released csdn, October 15, 2017, 20:39:26)

Posted by Spartan 117 on Fri, 06 Sep 2019 16:40:44 +0200

1,==,!=,<,>,<= and >= operators are comparison operators. The description of comparison operators in the Chinese version of C Language Specification 5.0 is as follows:

2. General Type System

3. Value Type Equal Function and Operator'='

3.1. Common types such as int, float, double, decimal, etc. inherit from ValueType, but they rewrite Equal inside the structure.

3.1.1, int, float, double, Equal function and'=='overloader function in decimal.

        Int32
        {
            public override bool Equals(Object obj) {
                if (!(obj is Int32)) {
                    return false;
                }
                return m_value == ((Int32)obj).m_value;
            }
     
            [System.Runtime.Versioning.NonVersionable]
            public bool Equals(Int32 obj)
            {
                return m_value == obj;
            }           
        }

        Double
        {
            // True if obj is another Double with the same value as the current instance.  This is
            // a method of object equality, that only returns true if obj is also a double.
            public override bool Equals(Object obj) {
                if (!(obj is Double)) {
                    return false;
                }
                double temp = ((Double)obj).m_value;
                // This code below is written this way for performance reasons i.e the != and == check is intentional.
                if (temp == m_value) {
                    return true;
                }
                return IsNaN(temp) && IsNaN(m_value);
            }
     
            public bool Equals(Double obj)
            {
                if (obj == m_value) {
                    return true;
                }
                return IsNaN(obj) && IsNaN(m_value);
            }    

            [System.Runtime.Versioning.NonVersionable]
            public static bool operator ==(Double left, Double right) {
                return left == right;
            }           
        }

        Single
        {
            public override bool Equals(Object obj) {
                if (!(obj is Single)) {
                    return false;
                }
                float temp = ((Single)obj).m_value;
                if (temp == m_value) {
                    return true;
                }
     
                return IsNaN(temp) && IsNaN(m_value);
            }
     
            public bool Equals(Single obj)
            {
                if (obj == m_value) {
                    return true;
                }
     
                return IsNaN(obj) && IsNaN(m_value);
            }

             [System.Runtime.Versioning.NonVersionable]
            public static bool operator ==(Single left, Single right) {
                return left == right;
            }           
        }

        Decimal
        {
            // Checks if this Decimal is equal to a given object. Returns true
            // if the given object is a boxed Decimal and its value is equal to the
            // value of this Decimal. Returns false otherwise.
            //
            [System.Security.SecuritySafeCritical]  // auto-generated
            public override bool Equals(Object value) {
                if (value is Decimal) {
                    Decimal other = (Decimal)value;
                    return FCallCompare(ref this, ref other) == 0;
                }
                return false;
            }
     
            [System.Security.SecuritySafeCritical]  // auto-generated
            public bool Equals(Decimal value)
            {
                return FCallCompare(ref this, ref value) == 0;
            }   

            [System.Security.SecuritySafeCritical]  // auto-generated
            public static bool operator ==(Decimal d1, Decimal d2) {
                return FCallCompare(ref d1, ref d2) == 0;
            }

            //I don't know the internal code of this function for the time being. If you know it, please let me know.
            //Based on the test results, it is assumed that if the two decimal numbers are equal, 0 will be returned.
            [System.Security.SecurityCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [MethodImplAttribute(MethodImplOptions.InternalCall)]
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            private static extern int FCallCompare(ref Decimal d1, ref Decimal d2);    

        }

3.1.2. Interested can go Reference Source Look at all the code.

3.1.3. Test code:

            //T is int ,float,double,decimal,byte,char
            T a = 1234567890;//0.1234567890f,0.123456789,1234567890M,(byte)11,'a'
            T b = 1234567890;//0.1234567890f,0.123456789,1234567890M,(byte)11,'a'
    
            Console.WriteLine(a == b);//Return true
            Console.WriteLine(a.Equals(b));//Return true
            Console.WriteLine(a.Equals((object)b));//Return true
            
            /*
            Console.WriteLine((object)a == b);//Compilation error: Operator'=='cannot be applied with'object' and'T'type operands
            Console.WriteLine(a == (object)b);//Compilation error: Operator'=='cannot be applied with'object' and'T'type operands
            //Console.WriteLine((object)a == (object)b);//Return to false, and explain why it is false. This is the reference type'==', which is described below.
            */

3.1.4. Conclusion: For simple common value types such as int, float, double, decimal, etc., the Equal function and operator'=', if its value is equal, return true; otherwise, return false.

3.2. Structural Structures

3.2.1. Equals functions within ValueType

        ValueType
        {
            [System.Security.SecuritySafeCritical]
            public override bool Equals (Object obj) {
                BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)");
                if (null==obj) {
                    return false;
                }
                RuntimeType thisType = (RuntimeType)this.GetType();
                RuntimeType thatType = (RuntimeType)obj.GetType();
     
                if (thatType!=thisType) {
                    return false;
                }
     
                Object thisObj = (Object)this;
                Object thisResult, thatResult;
     
                // if there are no GC references in this object we can avoid reflection 
                // and do a fast memcmp
                if (CanCompareBits(this))
                    return FastEqualsCheck(thisObj, obj);
     
                FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
     
                for (int i=0; i<thisFields.Length; i++) {
                    thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
                    thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);
                    
                    if (thisResult == null) {
                        if (thatResult != null)
                            return false;
                    }
                    else
                    if (!thisResult.Equals(thatResult)) {
                        return false;
                    }
                }
     
                return true;
            }
     
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [MethodImplAttribute(MethodImplOptions.InternalCall)]
            private static extern bool CanCompareBits(Object obj);
     
            [System.Security.SecuritySafeCritical]  // auto-generated
            [ResourceExposure(ResourceScope.None)]
            [MethodImplAttribute(MethodImplOptions.InternalCall)]
            private static extern bool FastEqualsCheck(Object a, Object b);         
        }

3.2.2, Structures (only value type, rewriting Equal function and operator'=')

3.2.2.1. Test code:

    struct Point
    {
        public double x;
        public double y;
        public double z;

        public Point(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }

        public override bool Equals(Object obj)
        {
            if (!(obj is Point))
            {
                return false;
            }

            if (((Point)obj).x == this.x)
            {
                return true;
            }

            return false;
        }
        public bool Equals(Point obj)
        {
            if (obj.x == this.x)
            {
                return true;
            }

            return false;
        }
        
        //The operator "Point.operator ==(Point, Point)" requires that the matching operator "!=" be defined as well.
        public static bool operator ==(Point left, Point right)
        {
            return left.x == right.x;
        }

        public static bool operator !=(Point left, Point right)
        {
            return left.x != right.x;
        }
    }

    Point p1 = new Point(1, 2, 3);
    Point p2 = p1;
    
    p1.y = 100;
    Console.WriteLine(p1 == p2);//Return true
    Console.WriteLine(p1.Equals(p2)); // Return true
    Console.WriteLine(p1.Equals((object)p2)); // Return true

3.2.2.2. Conclusion: At this point, the program executes the Equal function and operator'==', which we rewrote.

3.2.3, Structures (Value type only, no override of Equal function and operator'=')

3.2.3.1. Test code:

    struct Point
    {
        public double x;
        public double y;
        public double z;

        public Point(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }

    Point p1 = new Point(1, 2, 3);
    Point p2 = p1;

    Console.WriteLine(p1 == p2);//Compilation error: Operator "==" cannot be applied to operands of "Point" and "Point" types
    Console.WriteLine(p1.Equals(p2)); // Return true
    Console.WriteLine(p1.Equals((object)p2)); // Return true
    p1.y = 100;
    Console.WriteLine(p1.Equals(p2)); // Return false
    Console.WriteLine(p1.Equals((object)p2)); // Return false

3.2.3.2. When the program executes, CanCompareBits(this) returns true, and the code executes return Fast Equals Check (this Obj, obj);

3.2.3.3. Conclusion: The program judges the values of all fields in struct and returns true if they are all equal; otherwise, false.

3.2.4, Complex Structures (Value Type, Reference Type, Rewriting Equal Function and Operator'=')

3.2.4.1. Test code:

    public struct ValPoint
    {
        public double x;
        public double y;
        public double z;

        public ValPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
        
        public static bool operator ==(ValPoint left, ValPoint right)
        {
            return left.x == right.x;
        }

        public static bool operator !=(ValPoint left, ValPoint right)
        {
            return left.x != right.x;
        }
    }

    public class RefPoint
    {
        public double x;
        public double y;
        public double z;

        public RefPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }

    public struct ValLine
    {
        public ValPoint vPoint;       // Value type members

        public RefPoint rPoint;       // Reference type members

        public ValLine(ValPoint vPoint, RefPoint rPoint)
        {
            this.vPoint = vPoint;
            this.rPoint = rPoint;
        }

        public override bool Equals(Object obj)
        {
            if (!(obj is ValLine))
            {
                return false;
            }

            if (((ValLine)obj).vPoint == this.vPoint)
            {
                return true;
            }

            return false;
        }

        public bool Equals(ValLine obj)
        {
            if (obj.vPoint == this.vPoint)
            {
                return true;
            }

            return false;
        }

        public static bool operator ==(ValLine left, ValLine right)
        {
            return left.vPoint == right.vPoint;
        }

        public static bool operator !=(ValLine left, ValLine right)
        {
            return left.vPoint != right.vPoint;
        }
    }


    ValPoint vPoint = new ValPoint(1, 2, 3);
    ValPoint vPoint2 = new ValPoint(1, 2, 3);
    ValPoint vPoint3 = new ValPoint(10, 20, 30);
    RefPoint rPoint = new RefPoint(4, 5, 6);
    RefPoint rPoint2 = new RefPoint(7, 8, 9);

    ValLine p1 = new ValLine(vPoint, rPoint);
    ValLine p2 = p1;

    p2.vPoint = vPoint2;
    Console.WriteLine(p1 == p2); //Return true
    Console.WriteLine(p1.Equals(p2)); //Return true
    Console.WriteLine(p1.Equals((object)p2)); //Return true

    p2 = p1;
    p2.vPoint = vPoint3;
    Console.WriteLine(p1 == p2); //Return true
    Console.WriteLine(p1.Equals(p2)); //Return false
    Console.WriteLine(p1.Equals((object)p2)); //Return false

    p2 = p1;
    p2.rPoint = rPoint2;
    Console.WriteLine(p1 == p2); //Return true
    Console.WriteLine(p1.Equals(p2)); //Return true
    Console.WriteLine(p1.Equals((object)p2)); //Return true

3.2.4.2. Conclusion: At this point, the program executes the Equal function and operator'==', which we rewrote.

3.2.5, Complex Structures (Internal Value Type, Reference Type, Not Rewriting Equal Function and Operator'=')

3.2.5.1. Test code:

    public struct ValPoint
    {
        public double x;
        public double y;
        public double z;

        public ValPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }

    public class RefPoint
    {
        public double x;
        public double y;
        public double z;

        public RefPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }

    public struct ValLine
    {
        public ValPoint vPoint;       // Value type members

        public RefPoint rPoint;       // Reference type members

        public ValLine(ValPoint vPoint, RefPoint rPoint)
        {
            this.vPoint = vPoint;
            this.rPoint = rPoint;
        }
    }


    ValPoint vPoint = new ValPoint(1, 2, 3);
    ValPoint vPoint2 = new ValPoint(1, 2, 3);
    ValPoint vPoint3 = new ValPoint(10, 20, 30);
    RefPoint rPoint = new RefPoint(4, 5, 6);
    RefPoint rPoint2 = new RefPoint(7, 8, 9);

    ValLine p1 = new ValLine(vPoint, rPoint);
    ValLine p2 = p1;

    Console.WriteLine(p1 == p2);//Compilation error: Operator "==" cannot be applied to operands of "Point" and "Point" types

    p2.vPoint = vPoint2;
    Console.WriteLine(p1.Equals(p2)); //Return true
    Console.WriteLine(p1.Equals((object)p2)); //Return true

    p2 = p1;
    p2.vPoint = vPoint3;
    Console.WriteLine(p1.Equals(p2)); //Return false
    Console.WriteLine(p1.Equals((object)p2)); //Return false
    
    p2 = p1;
    p2.rPoint = rPoint2;
    Console.WriteLine(p1.Equals(p2)); //Return false
    Console.WriteLine(p1.Equals((object)p2)); //Return false

3.2.5.2. When the program executes, CanCompareBits(this) returns false, and the code executes the following statement of the ValueType class Equal function

                FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
     
                for (int i=0; i<thisFields.Length; i++) {
                    thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
                    thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);
                    
                    if (thisResult == null) {
                        if (thatResult != null)
                            return false;
                    }
                    else
                    if (!thisResult.Equals(thatResult)) {
                        return false;
                    }
                }
     
                return true;

3.2.5.3. Conclusion: The program judges all fields in struct, and the value type judges whether the value is equal; the reference type judges whether the reference is equal.

4. Reference Type Equal Function and Operator'='

4.1. String string

Introduction of String Equivalence Operators in Chinese Version 4.1.1 and C# Language Specification 5.0

4.1.2, Equal function of string and'=='overloaded operator function code

        String
        {
            // Determines whether two strings match.
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
            public override bool Equals(Object obj) {
                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);
            }
     
            // Determines whether two strings match.
            [Pure]
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
            public bool Equals(String value) {
                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);
            }

            public static bool operator == (String a, String b) {
               return String.Equals(a, b);
            }

            // Determines whether two Strings match.
            [Pure]
            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);
            }

            [System.Security.SecuritySafeCritical]  // auto-generated
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
            private unsafe static bool EqualsHelper(String strA, String strB)
            {
                Contract.Requires(strA != null);
                Contract.Requires(strB != null);
                Contract.Requires(strA.Length == strB.Length);
     
                int length = strA.Length;
     
                fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
                {
                    char* a = ap;
                    char* b = bp;
     
                    // unroll the loop
    #if AMD64
                    // for AMD64 bit platform we unroll by 12 and
                    // check 3 qword at a time. This is less code
                    // than the 32 bit case and is shorter
                    // pathlength
     
                    while (length >= 12)
                    {
                        if (*(long*)a     != *(long*)b) return false;
                        if (*(long*)(a+4) != *(long*)(b+4)) return false;
                        if (*(long*)(a+8) != *(long*)(b+8)) return false;
                        a += 12; b += 12; length -= 12;
                    }
    #else
                    while (length >= 10)
                    {
                        if (*(int*)a != *(int*)b) return false;
                        if (*(int*)(a+2) != *(int*)(b+2)) return false;
                        if (*(int*)(a+4) != *(int*)(b+4)) return false;
                        if (*(int*)(a+6) != *(int*)(b+6)) return false;
                        if (*(int*)(a+8) != *(int*)(b+8)) return false;
                        a += 10; b += 10; length -= 10;
                    }
    #endif
     
                    // This depends on the fact that the String objects are
                    // always zero terminated and that the terminating zero is not included
                    // in the length. For odd string sizes, the last compare will include
                    // the zero terminator.
                    while (length > 0) 
                    {
                        if (*(int*)a != *(int*)b) break;
                        a += 2; b += 2; length -= 2;
                    }
     
                    return (length <= 0);
                }
            }           

        }

4.1.3, Object. Reference Equals (this, value) If this and value are the same reference, return true; otherwise, return false.

            {
                string a = "a1!";
                string b = "a1!";
                Console.WriteLine(Object.ReferenceEquals(a, b));//Returning true, you can judge that the compiler optimizes the "a1!" pointed to by a and b into one place.
            }

            {
                string a = "Test";
                string b = string.Copy(a);
                Console.WriteLine(Object.ReferenceEquals(a, b));//Return false
            }

            {
                string a = "Test";
                string b = (string)a.Clone();
                Console.WriteLine(Object.ReferenceEquals(a, b));//Return true
            }

            {
                char[] ch = new char[] { 'a', 'A', '@' };
                string a = "aA@";
                string b = new string(ch);
                Console.WriteLine(Object.ReferenceEquals(a, b));//Return false
            }

4.1.4 Before learning the EqualsHelper(String strA, String strB) function, let's look at a piece of code

            unsafe
            {
                char[] firstCharA = "abc".ToCharArray();
                int length = firstCharA.Length;
                fixed (char* ap = firstCharA)
                {
                    for (int i = 0; i < length; i++)
                    {
                        Console.WriteLine(*(char*)(ap + i));
                    }
                }
            }

            unsafe
            {
                int[] firstCharA = new int[] { 1, 20, 300 };
                int length = firstCharA.Length;
                fixed (int* ap = firstCharA)
                {
                    for (int i = 0; i < length; i++)
                    {
                        Console.WriteLine(*(int*)(ap + i));
                    }
                }
            }            

4.1.5. Modified EqualsHelper(String strA, String strB) function

        private unsafe static bool EqualsHelper(String strA, String strB)
        {
            Contract.Requires(strA != null);
            Contract.Requires(strB != null);
            Contract.Requires(strA.Length == strB.Length);

            int length = strA.Length;

            char[] firstCharA = strA.ToCharArray();
            char[] firstCharB = strB.ToCharArray();

            fixed (char* ap = &firstCharA[0]) fixed (char* bp = &firstCharB[0])//Because I can't use m_firstChar, I modify it here by myself. ps: Personally, m_firstChar refers to the first character of a string, but it cannot be proved.
            //fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
            {
                char* a = ap;
                char* b = bp;
                
                while (length >= 10)
                {
                    if (*(int*)a != *(int*)b) return false;
                    if (*(int*)(a + 2) != *(int*)(b + 2)) return false;
                    if (*(int*)(a + 4) != *(int*)(b + 4)) return false;
                    if (*(int*)(a + 6) != *(int*)(b + 6)) return false;
                    if (*(int*)(a + 8) != *(int*)(b + 8)) return false;
                    a += 10; b += 10; length -= 10;
                }

                // This depends on the fact that the String objects are
                // always zero terminated and that the terminating zero is not included
                // in the length. For odd string sizes, the last compare will include
                // the zero terminator.
                while (length > 0)
                {
                    if (*(int*)a != *(int*)b) break;
                    a += 2; b += 2; length -= 2;
                }

                return (length <= 0);
            }
        }

4.1.6. Modification Notes

1,fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)-> fixed (char* ap = &firstCharA[0]) fixed (char* bp = &firstCharB[0])
2. (* (int*) a - > acquired two char values (low ASCII*65536 + high ASCII) [low ahead, high behind]. [Char two bytes, range U+0000 to U + FFFFFF]
3. (* (char*) a - > The data obtained is a char value [see the test example above]

4.1.7. Testing EqualsHelper(String strA, String strB) function

            {
                string a = "abcd";
                string b = "abcd";
                Console.WriteLine(EqualsHelper(a,b));//Return true
            }

            {
                string a = "Test";
                string b = string.Copy(a);
                Console.WriteLine(EqualsHelper(a, b));//Return true
            }

            {
                string a = "Test";
                string b = (string)a.Clone();
                Console.WriteLine(EqualsHelper(a, b));//Return true
            }

            {
                char[] ch = new char[] { 'a', 'A', '@' };
                string a = "aA@";
                string b = new string(ch);
                Console.WriteLine(EqualsHelper(a, b));//Return true
            }

4.1.8. Conclusion: String type A = b, string.Equals(a, b), a.Equals(b), a.Equals((object)b), true if the value of a is the same as that of b; otherwise false.

4.2. class

Introduction of Reference Type Equal Operators in Chinese Version 4.2.1 and C# Language Specification 5.0


4.2.2. Equals function inside Object

        Object
        {
            public virtual bool Equals(Object obj)
            {
                return RuntimeHelpers.Equals(this, obj);//Detailed code could not be found
            }
         
            public static bool Equals(Object objA, Object objB) 
            {
                if (objA==objB) {
                    return true;
                }
                if (objA==null || objB==null) {
                    return false;
                }
                return objA.Equals(objB);
            }
         
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [System.Runtime.Versioning.NonVersionable]
            public static bool ReferenceEquals (Object objA, Object objB) {
                return objA == objB;
            }
        } 

4.2.3, Class (not rewriting Equal function and operator'=')

    public class RefPoint
    {
        public double x;
        public double y;
        public double z;

        public RefPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }
    }
    
            RefPoint p1 = new RefPoint(4, 5, 6);
            RefPoint p2 = p1;
            Console.WriteLine(p1.Equals(p2));//Return true
            Console.WriteLine(object.Equals(p1, p2));//Return true
            Console.WriteLine(object.ReferenceEquals(p1, p2));//Return true
            Console.WriteLine(p1 == p2);//Return true

            p2 = new RefPoint(4, 5, 6);//Although the values are the same, the reference objects are different
            Console.WriteLine(p1.Equals(p2));//Return false
            Console.WriteLine(object.Equals(p1, p2));//Return false
            Console.WriteLine(object.ReferenceEquals(p1, p2));//Return false
            Console.WriteLine(p1 == p2);//Return false

4.2.4, Class (Rewriting Equal Function and Operator'=')

    public class RefPoint
    {
        public double x;
        public double y;
        public double z;

        public RefPoint(double X, double Y, double Z)
        {
            this.x = X;
            this.y = Y;
            this.z = Z;
        }

        public override bool Equals(Object obj)
        {
            if (!(obj is RefPoint))
            {
                return false;
            }

            if (((RefPoint)obj).x == this.x)
            {
                return true;
            }

            return false;
        }

        public bool Equals(RefPoint obj)
        {
            if (obj.x == this.x)
            {
                return true;
            }

            return false;
        }

        public static bool operator ==(RefPoint left, RefPoint right)
        {
            return left.x == right.x;
        }

        public static bool operator !=(RefPoint left, RefPoint right)
        {
            return left.x != right.x;
        }
    }

            RefPoint p1 = new RefPoint(4, 5, 6);
            RefPoint p2 = p1;
            Console.WriteLine(p1.Equals(p2));//Return true
            Console.WriteLine(object.Equals(p1, p2));//Return true
            Console.WriteLine(object.ReferenceEquals(p1, p2));//Return true
            Console.WriteLine(p1 == p2);//Return true

            p2 = new RefPoint(4, 50, 60);
            Console.WriteLine(p1.Equals(p2));//Return true
            Console.WriteLine(object.Equals(p1, p2));//Return true
            Console.WriteLine(object.ReferenceEquals(p1, p2));//Return false
            Console.WriteLine(p1 == p2);//Return true

4.2.5, Reference Equals (Object objA, Object objB) returns objA == objB. If objA and objB refer to the same object (it's useless to just decide whether to refer to the same object, even if we overload the'='operator ourselves), return true; otherwise, return false.

5. Summary

First, introduce the simple value type, then to the structure, string, class. Summarize the use of Equal and'=='for each type, deepen your memory, and hope to help you at the same time. Otherwise: This article only represents my point of view. If there is any mistake, please let me know.

6. Reference

6.1,C# Type Basis

6.2, C# Language Specification 5.0 Chinese Version

6.3,Reference Source

Topics: C# ascii less C