zoukankan      html  css  js  c++  java
  • C#之相等比较

      C#中的对象都继承自System.Object对象,分为引用类型和值类型两种,所以对象的相等比较而言就分两种,一种是比较引用,一种是比较值。System.Object默认提供了三个方法来进行对象的相等比较:静态的ReferenceEquals()和Equals()的两个版本,加上“==”运算符共有四种来进行对象相等比较的方法。

      相等比较的方法:静态的ReferenceEquals()、Equals()静态方法、Equals()虚方法(子类可以去重写)和“==”运算符。

      相等比较分类:引用类型比较(类的实例)、值类型比较(基本数据类型,结构或者枚举的实例)。

      但对于引用类型和值类型而言,同一个方法它们的内部比较逻辑是不一样的,下面进行下简单的介绍。

    一、引用类型相等比较

    1、静态的ReferenceEquals()

      ReferenceEquals()是一个静态方法,比较两个对象是否引用自同一个地址,是则返回true,否则返回false

      调用方法:ReferenceEquals(obj1,obj2)

      比较原则:1)、obj1和obj2同为null,则返回true

             2)、obj1和obj2只有一个为null,则返回false

           3)、obj1和obj2均不为null时,比较两个对象的引用地址,是则返回true,不是则返回false

      例子:

        SomeClass x,y;

        x = new SomeClass();

        y = new SomeClass();

        z = y;

        Boolean result1 = ReferenceEquals(null,null);  //return true

        Boolean result2 = ReferenceEquals(null,x);   //return false

        Boolean result3 = ReferenceEquals(x,y);    //return false

        Boolean result4 = ReferenceEquals(y,z);    //return true

    2、虚拟的Equals()方法

      System.Object()的虚拟的Equals()方法也是比较引用的,但是因为它是虚拟的,所以继承的子类可以重写该方法以实现按值来比较对象,在重写Equals()方法时最好重写对象的GetHashCode()方法.

    View Code
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Point p1 = new Point(5, 2);
                Point p2 = new Point(5, 2);
                Point3D p3 = new Point3D(5, 2, 1);
                Point3D p4 = new Point3D(5, 2, 1);
    
                if (p1.Equals(p2))
                    Console.WriteLine("p1 is equals p2");
                if (p3.Equals(p4))
                    Console.WriteLine("p3 is equals p4");
    
                if (!p1.Equals(p3))
                    Console.WriteLine("p1 is not equals p3");
    
                if (!p3.Equals(p1))
                    Console.WriteLine("p3 is not equals p1");
            }
        }
    
        public class Point
        {
            private Int32 x;
            private Int32 y;
    
            public Point()
            {
                this.x = 0;
                this.y = 0;
            }
            public Point(Int32 _x, Int32 _y)
            {
                this.x = _x;
                this.y = _y;
            }
    
            public Int32 X
            {
                get { return x; }
                set { x = value; }
            }
    
            public Int32 Y
            {
                get { return y; }
                set { y = value; }
            }
    
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;
    
                if (this.GetType() != obj.GetType())
                    return false;
    
    
                return Equals((Point)obj);
            }
    
            public override int GetHashCode()
            {
                return x ^ y;
                //return base.GetHashCode();
            }
    
            public override string ToString()
            {
                return String.Format("X:{0},Y:{1}", this.x, this.y);
                //return base.ToString();
            }
    
            private bool Equals(Point p)
            {
                return (this.x == p.x) && (this.y == p.y);
            }
        }
    
        public class Point3D : Point
        {
            private Int32 z;
            public Int32 Z
            {
                get { return this.z; }
                set { z = value; }
            }
    
            public Point3D()
                : base()
            {
                this.z = 0;
            }
    
            public Point3D(Int32 _x, Int32 _y, Int32 _z)
                : base(_x, _y)
            {
                this.z = _z;
            }
    
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;
                if (GetType() != obj.GetType())
                    return false;
    
                Point3D p3d = obj as Point3D;
    
                if (p3d.z != this.z)
                    return false;
    
                return base.Equals(obj);
            }
    
            public override int GetHashCode()
            {
                return base.GetHashCode() ^ z;
            }
    
            public override string ToString()
            {
                return String.Format("X:{0},Y:{1},Z:{2}", base.X, base.Y, Z);
            }
        }
    }

    3、静态的Equals()方法

      Eauals()静态方法的比较原则是按照引用的方式比较,再调用对象的Equals()方法的实例版本进行比较,所以在重写对象的Equals()方法时,其实已经间接的重写了静态的Equals()方法。

      调用方法:Equals(obj1,obj2)

      比较原则:1)、obj1和obj2均为null,则返回true

           2)、obj1和obj2中只有一个为null,则返回false

           3)、如果obj1和obj2两个引用不指向同一个对象,则返回false

           4)、如果obj1和obj2两个引用指向同一个对象,则调用它们的Equals()方法的实例版本进行比较

    4、“==”比较运算符

      在默认情况下,==运算符对引用类型比较的是两个对象指向的引用是否是同一个对象,但是作为一个自定义的复杂类,可以自己重写适合自己的“==”运算符,在重写“==”时必须同时重写“!=”运算符。

      例1:在没有重写“==”时,我们看下两个类的“==”的比较结果(比较是否指向同一个引用)

    View Code
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Point p1 = new Point(5, 2);
                Point p2 = new Point(5, 2);
                Point p21 = p1;
    
                if (p1.Equals(p2))
                    Console.WriteLine("p1 is equals p2");
    
                if (!(p1 == p2))
                    Console.WriteLine("p1 is not == p2");
    
                if (p1 == p21)
                    Console.WriteLine("p1 is == p21");
            }
        }
    
        public class Point
        {
            private Int32 x;
            private Int32 y;
    
            public Point()
            {
                this.x = 0;
                this.y = 0;
            }
            public Point(Int32 _x, Int32 _y)
            {
                this.x = _x;
                this.y = _y;
            }
    
            public Int32 X
            {
                get { return x; }
                set { x = value; }
            }
    
            public Int32 Y
            {
                get { return y; }
                set { y = value; }
            }
    
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;
    
                if (this.GetType() != obj.GetType())
                    return false;
    
    
                return Equals((Point)obj);
            }
    
            public override int GetHashCode()
            {
                return x ^ y;
                //return base.GetHashCode();
            }
    
            public override string ToString()
            {
                return String.Format("X:{0},Y:{1}", this.x, this.y);
                //return base.ToString();
            }
    
            private bool Equals(Point p)
            {
                return (this.x == p.x) && (this.y == p.y);
            }
        }
    }

      运算结果:

      例2:我们重写“==”运算符(比较两个对象对应值是否相等),这时再看下结果

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Point p1 = new Point(5, 2);
                Point p2 = new Point(5, 2);
                Point p21 = p1;
    
                if (p1.Equals(p2))
                    Console.WriteLine("p1 is equals p2");
    
                if (p1 == p2)
                    Console.WriteLine("p1 is == p2");
    
                if (p1 == p21)
                    Console.WriteLine("p1 is == p21");
            }
        }
    
        public class Point
        {
            private Int32 x;
            private Int32 y;
    
            public Point()
            {
                this.x = 0;
                this.y = 0;
            }
            public Point(Int32 _x, Int32 _y)
            {
                this.x = _x;
                this.y = _y;
            }
    
            public Int32 X
            {
                get { return x; }
                set { x = value; }
            }
    
            public Int32 Y
            {
                get { return y; }
                set { y = value; }
            }
    
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;
    
                if (this.GetType() != obj.GetType())
                    return false;
    
    
                return Equals((Point)obj);
            }
    
            /// <summary>
            /// 重写相等运算符
            /// </summary>
            public static Boolean operator ==(Point p1, Point p2)
            {
                return (p1.x == p2.x) && (p1.y == p2.y);
            }
    
            /// <summary>
            /// 重写不相等运算符
            /// </summary>
            public static Boolean operator !=(Point p1, Point p2)
            {
                return !(p1.x == p2.x) && (p1.y == p2.y);
            }
    
            public override int GetHashCode()
            {
                return x ^ y;
                //return base.GetHashCode();
            }
    
            public override string ToString()
            {
                return String.Format("X:{0},Y:{1}", this.x, this.y);
                //return base.ToString();
            }
    
            private bool Equals(Point p)
            {
                return (this.x == p.x) && (this.y == p.y);
            }
        }
    }

      运算结果:

    二、值类型相等比较

    1、静态的ReferenceEquals()

      ReferenceEquals()方法用于比较引用,在比较之前,C#会先通过装箱技术对每个值类型参数进行分别装箱,这样ReferenceEquals()方法进行比较时得到的结果永远时false,所以用ReferenceEquals()来比较值类型是没有什么意义的。

    2、虚拟的Equals()方法、静态的Equals()方法和“==”运算符

      对于值类型,这三个方法默认都是进行值比较的。

    View Code
    namespace ConsoleApp
    {
        class Program
        {
            static void Main(string[] args)
            {
    
                Int32 a = 5;
                Int32 b = 5;
    
                if (a.Equals(b))
                    Console.WriteLine("a is equals b");
                if (a == b)
                    Console.WriteLine("a is == b");
    
                if (Equals(a, b))
                    Console.WriteLine("a is equals b");
    
                if (!ReferenceEquals(a, b))
                    Console.WriteLine("a is not ReferenceEquals b");
            }
        }
    }

        

  • 相关阅读:
    C++——并发编程
    Poco C++——JSON解析
    #转载#我给所有新手程序员的建议
    #笔记# 如何阅读技术类书籍
    笔记:CSS hack的学习与了解…
    【笔记】CSS选择器整理(IE低版本支持性测试)
    呼吸灯效果
    ajax跨域问题-----jsonp
    【转】js里的时间函数集
    grunt与requirejs结合使用
  • 原文地址:https://www.cnblogs.com/NaughtyBoy/p/2538464.html
Copyright © 2011-2022 走看看