zoukankan      html  css  js  c++  java
  • 细说对象的相等性

    1 从Object.Equals方法说起

    使用Object.Equals方法能够确定两个Object实例是否相等。

    Object.Equals方法具有下面重载形式:

    (1)Object.Equals (Object) 

    该方法能够确定指定的Object是否等于当前的Object。相等时返回true,否则返回false。

    (2)Object.Equals (Object, Object) 

    该方法能够确定指定的两个Object实例是否相等。相等时返回true,否则返回false。此方法为静态方法。

    例1 定义Student类,并使用Object.Equals方法确定Student实例是否相等。

    using System;
    namespace IEquatableExp
    {
        public class Student
        {
            private int studentID;
            private string studentName;
            private int age;
            public Student(int studentID, string studentName, int age)
            {
                this.studentID = studentID;
                this.studentName = studentName;
                this.age = age;
            }
            public int StudentID
            {
                get { return this.studentID;}
            }
            public string StudentName
            {
                get { return this.studentName; }
            }
            public int Age
            {
                get { return this.age; }
            }
        }
    }
    using System;
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student(1,"tiana",25);
                Student stu2 = stu1;
                Student stu3 = new Student(stu1.StudentID,stu1.StudentName,stu1.Age);
                Console.WriteLine("(Student)stu1, (Student)stu2,(Student)stu3: ");
                Console.WriteLine("stu1.Equals(stu2) = {0}", stu1.Equals(stu2));
                Console.WriteLine("stu1.Equals(stu3) = {0}", stu1.Equals(stu3));
                Console.WriteLine("Object.Equals(stu1, stu2) = {0}", Object.Equals(stu1, stu2));
                Console.WriteLine("Object.Equals(stu1, stu3) = {0}", Object.Equals(stu1, stu3));
            }
        }
    }

    代码执行结果例如以下图所看到的:

      

    从例1的执行结果能够了解到:

    Object.Equals方法的默认实现仅支持引用相等。

     

    2 说说引用相等和值相等

    对于引用类型,Object.Equals方法会去推断对象的引用是否指向的是同一个对象,若指向的是同一个对象则觉得是引用相等

    如例1中的引用stu1与stu2指向同样的对象,而引用stu3指向了还有一个对象,所以调用Object.Equals方法确认stu1与stu2的相等性时会返回true,调用Object.Equals方法确认stu1与stu3的相等性时会返回false,虽然此时stu3指向的对象的值与stu1指向的对象的值同样。

    对于值类型,Object.Equals方法是依据对象的值来确定对象的相等性的(MSDN上也称为按位相等)。此乃值相等也。

    对于前面样例中的Student类,若改动其类型为struct,其它代码均不变,运行结果又会是如何的呢。

    using System;
    namespace IEquatableExp
    {
    //改动Student的类型为struct
        public struct Student
        {
            //此部分代码不变
        }
    }

    改动代码后再次运行程序,得到下面结果。


    由于struct是值类型,所以通过Object.Equals方法确定struct对象是否相等是依据对象的值来推断的,非常显然样例中的stu1,stu2,stu3的值均同样,所以结果返回true。

     

    3 C#中的值类型和引用类型

    C#中,值类型包含:整型,长整型,浮点型,字符型,布尔型,枚举和结构体等。

    引用类型包含:基类Object,字符串,用户自己定义的类,接口和数组等。

     

    4 再来看一个使用Object.Equals方法的样例

    以下通过例2来进一步说明Object.Equals方法的使用。

    例2 代码中使用Object.Equals方法对整型,字符串,可变字符字符串是否相等进行推断。

    using System;
    using System.Text;
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                int a = 32;
                int b = 32;
                Console.WriteLine("(int)a = {0}; (int)b = {1}:", a, b);
                Console.WriteLine("a.Equals(b) = {0}", a.Equals(b));
                Console.WriteLine("Object.Equals(a, b) = {0}", Object.Equals(a, b));
     
                Console.WriteLine();
     
                string str1 = "tiana";
                string str2 = "tiana";
                Console.WriteLine("(string)str1 = {0}; (string)str2 = {1}:", str1, str2);
                Console.WriteLine("str1.Equals(str2) = {0}", str1.Equals(str2));
                Console.WriteLine("Object.Equals(str1, str2) = {0}", Object.Equals(str1, str2));
     
                Console.WriteLine();
     
                StringBuilder sb1 = new StringBuilder("tiana");
                StringBuilder sb2 = new StringBuilder("tiana");
                Console.WriteLine("(StringBuilder)sb1 = {0}; (StringBuilder)sb2 = {1}:", sb1, sb2);
                Console.WriteLine("sb1.Equals(sb2) = {0}", sb1.Equals(sb2));
                Console.WriteLine("Object.Equals(sb1, sb2) = {0}", Object.Equals(sb1, sb2));
            }
        }
    }

    代码运行结果例如以下图所看到的:

     

    对于整型,我们无需做过多说明,由于当整型对象的值相等时即觉得对象相等。

    对于字符串,虽然字符串是引用类型,可是字符串类String中已经对Object.Equals方法进行了重写,使字符串类支持值相等。

    查看String类的源码,你会发现String类提供了下面几个Equals方法的重载。

     

    当中Equals(Object):Boolean方法便是对Object.Equals方法的重写。

    对于可变字符字符串类StringBuilder,我们相同通过查看其源码来分析结果产生的原因。

    查看源码能够了解到,StringBuilder类仅提供了自己的Equals方法,而并没有重写Object.Equals方法,所以实例中“sb1.Equals(sb2)”会调用StringBuilder类自己实现的Equals方法,该方法被实现成支持值相等,而“Object.Equals(sb1, sb2)”部分仍然会调用Object.Equals方法的实现,依照引用来确认对象是否相等。正由于此,所以会出现样例中的结果。

     

    通过分析例2的执行情况,我们能够学习到:

    Object.Equals的默认实现仅支持引用相等,但派生类可重写此方法以支持值相等。

    例2中的String类与StringBuilder类能够非常好的说明这点。

     

    5 自娱自乐一下

    以下给出一个非常小的样例,供大家自娱自乐一下。

    例3 大家知道以下代码的运行结果吗?要是知道的话,请大声说出来吧。

    using System;
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                int a = 32;
                byte b = 32;
                Console.WriteLine("(int)a = {0}; (byte)b = {1}:", a, b);
                Console.WriteLine("a.Equals(b) = {0}", a.Equals(b));
                Console.WriteLine("a.Equals(b) = {0}", b.Equals(a));
             }
        }
    }

    不知道的话,那就直接看以下的结果。

     

    为什么会这样?大家自己去琢磨吧。

      

    6 在Student类中重写Object.Equals方法

    接下来,我们要再次改动我们的Student类,在类中重写Object.Equals方法使其支持值相等。

    例4 使我们的Student类支持值相等

    using System;
    namespace IEquatableExp
    {
        public class Student
        {
            private int studentID;
            private string studentName;
            private int age;
            public Student(int studentID, string studentName, int age)
            {
                this.studentID = studentID;
                this.studentName = studentName;
                this.age = age;
            }
            public int StudentID
            {
                get { return this.studentID;}
            }
            public string StudentName
            {
                get { return this.studentName; }
            }
            public int Age
            {
                get { return this.age; }
            }
     
            public override bool Equals(Object otherObject)
            {
                if (otherObject == null)
                {
                    return false;
                }
                Student otherStudent = otherObject as Student;
                if (otherStudent == null)
                {
                    return false;
                }
                else
                {
                    return (this.StudentName == otherStudent.StudentName)
                        && (this.StudentID == otherStudent.StudentID)
                        && (this.Age == otherStudent.Age);
                }
            }
     
            public override int GetHashCode()
            {
                return this.StudentID.GetHashCode();
            }
        }
    }
    using System;
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student(1, "tiana", 25);
                Student stu2 = stu1;
                Student stu3 = new Student(stu1.StudentID, stu1.StudentName, stu1.Age);
                Console.WriteLine("(Student)stu1, (Student)stu2, (Student)stu3: ");
                Console.WriteLine("stu1.Equals(stu2) = {0}", stu1.Equals(stu2));
                Console.WriteLine("stu1.Equals(stu3) = {0}", stu1.Equals(stu3));
                Console.WriteLine("Object.Equals(stu1, stu2) = {0}", Object.Equals(stu1, stu2));
                Console.WriteLine("Object.Equals(stu1, stu3) = {0}", Object.Equals(stu1, stu3));
            }
        }
    }

    执行程序,得到下面结果:

     

    由于stu1,stu2,stu3的值相等,所以程序会返回true。

     

    7 使我们的Student类实现IEquatable(T)接口

    例5 实现IEquatable(T)接口

    using System;
    namespace IEquatableExp
    {
        public class Student:IEquatable<Student>
        {
            private int studentID;
            private string studentName;
            private int age;
            public Student(int studentID, string studentName, int age)
            {
                this.studentID = studentID;
                this.studentName = studentName;
                this.age = age;
            }
            public int StudentID
            {
                get { return this.studentID;}
            }
            public string StudentName
            {
                get { return this.studentName; }
            }
            public int Age
            {
                get { return this.age; }
            }
     
            public bool Equals(Student otherStudent)
            {
                if (otherStudent == null)
                {
                    return false;
                }
                return (this.StudentName == otherStudent.StudentName)
                        && (this.StudentID == otherStudent.StudentID)
                        && (this.Age == otherStudent.Age);
            }
     
            public override bool Equals(Object otherObject)
            {
                if (otherObject == null)
                {
                    return false;
                }
                Student otherStudent = otherObject as Student;
                if (otherStudent == null)
                {
                    return false;
                }
                else
                {
                    return Equals(otherStudent);
                }
            }
     
            public override int GetHashCode()
            {
                return this.StudentID.GetHashCode();
            }
        }
    }
    using System;
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student(1, "tiana", 25);
                Student stu2 = stu1;
                Student stu3 = new Student(stu1.StudentID, stu1.StudentName, stu1.Age);
                Console.WriteLine("(Student)stu1, (Student)stu2,(Student)stu3: ");
                Console.WriteLine("stu1.Equals(stu2) = {0}", stu1.Equals(stu2));
                Console.WriteLine("stu1.Equals(stu3) = {0}", stu1.Equals(stu3));
                Console.WriteLine("Object.Equals(stu1, stu2) = {0}", Object.Equals(stu1, stu2));
                Console.WriteLine("Object.Equals(stu1, stu3) = {0}", Object.Equals(stu1, stu3));
            }
        }
    }

    代码执行结果例如以下图所看到的:

     

    IEquatable(T)接口提供了Equals方法的定义,实现该接口的类须要提供Equals方法的实现,我们在Student类中实现了IEquatable(T)接口的Equals方法并重写了Object.Equals方法,使其均支持值相等。这样一来,能够使Object.Equals方法的行为与IEquatable<T>.Equals方法的行为保持一致。

    至于程序的执行结果我就不做过多解释了,相信大家都能看得懂。

     

    8 重载op_Equality和op_Inequality运算符

    最后,在我们的Student类中,重载op_Equalityop_Inequality运算符

    例6 此实例仅包括部分代码,以下所给代码是在例5的Student类中新增的代码

    public static bool operator ==(Student student1, Student student2)
    {
         if ((object)student1 == null || (object)student2 == null)
         {
              return Object.Equals(student1, student2);
         }
         return student1.Equals(student2);
    }
     
    public static bool operator !=(Student student1, Student student2)
    {
         if ((object)student1 == null || (object)student2 == null)
         {
              return !Object.Equals(student1, student2);
         }
         return !student1.Equals(student2);
    }
    同一时候给出測试代码。

    using System; 
    namespace IEquatableExp
    {
        class Program
        {
            static void Main(string[] args)
            {
                Student stu1 = new Student(1, "tiana", 25);
                Student stu2 = stu1;
                Student stu3 = new Student(stu1.StudentID, stu1.StudentName, stu1.Age);
                Console.WriteLine("(Student)stu1, (Student)stu2,(Student)stu3: ");
                Console.WriteLine("stu1 == stu2 = {0}", stu1 == stu2);
                Console.WriteLine("stu1 != stu3 = {0}", stu1 != stu3);
            }
        }
    }

    执行结果例如以下图所看到的:

     

    到这里,我们便能够确保全部測试相等性返回的结果均保持一致。

     

    好了,就到这里了。

    88

     

     

     

     

     

  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3762448.html
Copyright © 2011-2022 走看看