c# Equal函數 and 運算符'==' (原發佈 csdn 2017年10月15日 20:39:26)

来源:https://www.cnblogs.com/njit-77/archive/2019/09/05/11468934.html
-Advertisement-
Play Games

1、==、!=、、= 運算符為比較運算符(comparison operator)。C 語言規範5.0中文版中比較運算符的描述如下: 2、通用類型系統 3、值類型Equal函數 and 運算符'==' 3.1、常見類型 int、float、double、decimal等雖然繼承自ValueType, ...


1、==、!=、<、>、<= 和>= 運算符為比較運算符(comparison operator)。C#語言規範5.0中文版中比較運算符的描述如下:

這裡寫圖片描述

2、通用類型系統

這裡寫圖片描述

3、值類型Equal函數 and 運算符'=='

3.1、常見類型 int、float、double、decimal等雖然繼承自ValueType,但其結構體內部重寫了Equal。

3.1.1、 int,float,double,decimal內部的Equal函數和 '=='重載符函數。

        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;
            }

            //暫時不知道此函數內部代碼,如有知道還望告知。
            //根據測試結果,推測如果兩個decimal數相等,返回0
            [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、感興趣的可去Reference Source查看全部代碼。

3.1.3、測試代碼:

            //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);//返回true
            Console.WriteLine(a.Equals(b));//返回true
            Console.WriteLine(a.Equals((object)b));//返回true
            
            /*
            Console.WriteLine((object)a == b);//編譯錯誤:運算符‘==’無法應用與‘object’和‘T’類型操作數
            Console.WriteLine(a == (object)b);//編譯錯誤:運算符‘==’無法應用與‘object’和‘T’類型操作數
            //Console.WriteLine((object)a == (object)b);//返回false,下麵解釋為什麼是false。這個是引用類型'==',放到下文介紹
            */

3.1.4、結論:對於簡單常見值類型 int、float、double、decimal等,Equal函數 and 運算符'==',如果其值相等,返回true;否則,返回false。

3.2、 結構體struct

3.2.1、 ValueType內部的Equals函數

        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、結構體(只有值類型,重寫Equal函數 and 運算符'==')

3.2.2.1、測試代碼:

    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;
        }
        
        //運算符“Point.operator ==(Point, Point)”要求也要定義匹配的運算符“!=”
        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);//返回true
    Console.WriteLine(p1.Equals(p2)); // 返回true
    Console.WriteLine(p1.Equals((object)p2)); // 返回true

3.2.2.2、結論:此時程式執行我們重寫的Equal函數 and 運算符'=='。

3.2.3、結構體(只有值類型,不重寫Equal函數 and 運算符'==')

3.2.3.1、測試代碼:

    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);//編譯錯誤:運算符"=="無法應用於"Point"和"Point"類型的操作數
    Console.WriteLine(p1.Equals(p2)); // 返回true
    Console.WriteLine(p1.Equals((object)p2)); // 返回true
    p1.y = 100;
    Console.WriteLine(p1.Equals(p2)); // 返回false
    Console.WriteLine(p1.Equals((object)p2)); // 返回false

3.2.3.2、程式執行時,CanCompareBits(this)返回true,代碼執行return FastEqualsCheck(thisObj, obj);

3.2.3.3、結論:程式判斷struct裡面所有欄位的值,如果全部相等,返回true;否則,返回false。

3.2.4、複雜結構體(有值類型、引用類型,重寫Equal函數 and 運算符'==')

3.2.4.1、測試代碼:

    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;       // 值類型成員

        public RefPoint rPoint;       // 引用類型成員

        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); //返回true
    Console.WriteLine(p1.Equals(p2)); //返回true
    Console.WriteLine(p1.Equals((object)p2)); //返回true

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

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

3.2.4.2、結論:此時程式執行我們重寫的Equal函數 and 運算符'=='。

3.2.5、複雜結構體(內部值類型、引用類型,不重寫Equal函數 and 運算符'==')

3.2.5.1、測試代碼:

    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;       // 值類型成員

        public RefPoint rPoint;       // 引用類型成員

        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);//編譯錯誤:運算符"=="無法應用於"Point"和"Point"類型的操作數

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

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

3.2.5.2、程式執行時,CanCompareBits(this)返回false,代碼執行ValueType類Equal函數的下麵語句

                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、結論:程式判斷struct裡面所有欄位,值類型就判斷值是否相等;引用類型就判斷是否引用相等。

4、引用類型Equal函數 and 運算符'=='

4.1、字元串string

4.1.1、C#語言規範5.0中文版中的字元串相等運算符介紹

這裡寫圖片描述

4.1.2、string的Equal函數和'=='重載運算符函數代碼

        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.ReferenceEquals(this, value)如果this、value是同一個引用,返回true;否則,返回false。

            {
                string a = "a1!";
                string b = "a1!";
                Console.WriteLine(Object.ReferenceEquals(a, b));//返回true,可以判斷編譯器將a與b所指向的"a1!"優化成一個地方。
            }

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

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

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

4.1.4、學習EqualsHelper(String strA, String strB)函數之前,我們先看一段代碼

            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、修改後EqualsHelper(String strA, String strB)函數

        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])//因無法使用m_firstChar,此處是我自行修改。ps:個人認為m_firstChar是指字元串的第一字元,但是無法證明。
            //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、修改說明

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->獲取的數據是兩個char值(低位ASCII*65536+高位ASCII)[低位在前,高位在後]。 [char兩個位元組,範圍U+0000到U+FFFF]
3、(*(char*)a->獲取的數據是一個char值[見上面測試例子]

4.1.7、測試EqualsHelper(String strA, String strB)函數

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

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

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

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

4.1.8、結論:string類型 a == b、string.Equals(a, b)、a.Equals(b)、a.Equals((object)b),如果 a 的值與 b 的值相同,則為 true;否則為 false。

4.2、類class

4.2.1、C#語言規範5.0中文版中的引用類型相等運算符介紹

這裡寫圖片描述
這裡寫圖片描述

4.2.2、Object內部的Equals函數

        Object
        {
            public virtual bool Equals(Object obj)
            {
                return RuntimeHelpers.Equals(this, obj);//無法查到詳細代碼
            }
         
            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、類(不重寫Equal函數 and 運算符'==')

    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));//返回true
            Console.WriteLine(object.Equals(p1, p2));//返回true
            Console.WriteLine(object.ReferenceEquals(p1, p2));//返回true
            Console.WriteLine(p1 == p2);//返回true

            p2 = new RefPoint(4, 5, 6);//雖然值一樣,但是引用對象不一樣
            Console.WriteLine(p1.Equals(p2));//返回false
            Console.WriteLine(object.Equals(p1, p2));//返回false
            Console.WriteLine(object.ReferenceEquals(p1, p2));//返回false
            Console.WriteLine(p1 == p2);//返回false

4.2.4、類(重寫Equal函數 and 運算符'==')

    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));//返回true
            Console.WriteLine(object.Equals(p1, p2));//返回true
            Console.WriteLine(object.ReferenceEquals(p1, p2));//返回true
            Console.WriteLine(p1 == p2);//返回true

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

4.2.5、ReferenceEquals (Object objA, Object objB)返回objA == objB。如果objA、 objB引用同一個對象(只判斷是否引用同一個對象,即使我們自行重載了'=='運算符,也沒用),返回true;否則,返回false。

5、總結

先介紹簡單值類型,再到結構體,字元串,類。把每個類型Equal和'=='用法做個總結,加深自己記憶的同時,也希望能幫助到你。另:本文只代表本人觀點,如果有誤,還望告知。

6、參考

6.1、C#類型基礎

6.2、 C#語言規範5.0中文版

6.3、Reference Source


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
  • 前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 GitHub:https://github.com/kwwwvagaa/NetWinformControl 碼雲:https://gitee.com/kwwwvagaa/net_winform_custom_contr ...
  • 一、使用nuget下載swagger包 Install-Package Swashbuckle 二、配置swagger 1. 安裝完Swashbuckle後,nuget會將相關引用添加至WebApi項目,其中會在App_Start文件夾下添加一個SwaggerConfig.cs文件,如下圖所示: 2 ...
  • 1 創建項目 以Visual Studio作為開發工具,測試平臺為Revit 2017 打開VS,創建一個C .NET Framwork類庫項目,選擇。.net框架版本為 ,確定。 2 項目設置 1. 引用相關 和`RevitAPIUI.dll 複製本地 平臺目標 x64`。 2. VS自動為你創建 ...
  • 場景 有時候需要根據配置文件在窗體中使用代碼動態生成控制項。 比如讀取xml配置文件中的節點數量,然後在窗體中生成指定數量的RadioGroup控制項。 實現 新建一個窗體,在窗體的載入完之後的事件中 傳入配置文件路徑,然後生成控制項。 註: 1.生成控制項對象。 2.設置控制項對象的顯示值text屬性以及寬 ...
  • 錯誤提示如圖: 檢查C:\Windows\System32\inetsrv\config目錄下的applicationHost.config文件,備份一份。 可使用IIS提供的AppCmd.exe的restore功能恢復applicationHost.config文件 運行CMD 輸入 cd %wi ...
  • 上是效果圖我這裡使用的是兩張表作為父子節點的分配,網上很多demo是一張表的那張一般作為導航欄用。 1 public void Bind(DataTable dt) 2 { 3 this.equiplist.ClearNodes(); 4 if (dt.Rows.Count > 0) 5 { 6 7... ...
  • 場景 點擊按鈕使窗體以Dialog的方式顯示,即彈窗。 然後設置彈窗的位置居中顯示。 關註公眾號霸道的程式猿獲取編程相關電子書、教程推送與免費下載。 實現 以上設置顯示在屏幕中間,其他選項如下: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...