1. 程式人生 > >比較物件相等性的四種方法

比較物件相等性的四種方法

比較物件相等性的四種方法

        System.Object定義了3個不同的方法,來比較物件的相等性:ReferenceEquals()和兩個版本的Equals()。再加上比較運算子(==),實際上是有四種比較相等的方式。

    在程式設計中實際上我們只需要這兩種比較,c#中型別也就這兩種

  (1)值型別的比較:一般我們就是判斷兩個值型別例項的各自包含的值是否相等

  (2)引用型別的比較:由於引用型別在記憶體中的分佈有兩部分,一個是引用型別的引用(存在於執行緒棧中),一個是引用型別的值(存在於託管堆);所以我們比較引用型別也就存在兩種比較

    預設情況下:值型別比較的是兩個值是否相等(不裝箱情況下),引用型別比較的是兩個引用是否相等。

1.ReferenceEquals()

        ReferenceEquals()是一個靜態方法,測試兩個引用是否引用類的同一個例項。特別是兩個引用是否包含記憶體中的相同地址。作為靜態方法,他不能重寫,所以system.Object的實現程式碼保持不變。

2.虛方法Equals()

        Equals()虛擬版本的System.Object實現程式碼也可以用於比較引用。但因為這個方法是虛方法,所以可以在自己的類中重寫他,從而按值來比較物件。

        注意:對於Object物件比較的是引用!然而對於值型別,型別相同(不會進行型別自動轉換),並且數值相同(對於struct的每個成員都必須相同),則Equals返回 true,否則返回false。這是為什麼呢? 這是因為內建的值型別都重寫了Object.Equals方法,所以值型別的Equals方法與引用型別的Equals就產生了不同的效果。

      Equals在程式執行時決定比較的型別--根據物件的實際型別進行比較,根據物件的型別呼叫他們各自的Equals虛方法。

3.靜態的Equals()方法

        Equals()的靜態版本與虛擬例項版本的作用相同,其區別是靜態版本帶有兩個引數,並對他們進行相等性的比較。

        用反編譯工具反編譯System.dll得到方法的實現原始碼:

  public static bool Equals(object objA, object objB)
    {
          if (objA == objB)
         { return true; }
         if ((objA != null) && (objB != null))
         { return objA.Equals(objB); }
        return false;
     }

 

4.比較運算子(==)

        定義:靜態相等符號,對應存在的!=,這個符號是一個可以過載的二元操作符,可以用於比較兩個物件是否相等。使用==比較物件時,C#在編譯時就決定了所比較的型別,而且不會執行任何虛方法(Object.Equals)。這是大家所期望的相等行比較。

  • 對於內建值型別,==判斷的是兩個物件的代數值是否相等。它會根據需要自動進行必要的型別轉換,並根據兩個物件的值是否相等返回true或者false
  • 對於引用型別,則==一般情況下比較的這是引用型別的引用是否相等。

  注意:但是某些內建的引用型別過載了==符號,例如string就過載==,使其比較的不是兩個字串的引用,而是比較的兩個字串字面量是否相等,所以對於引用型別最好不要使用==符號進行相等性比較,避免混淆。

    【對於引用型別利用==除了string是比較其值外,其餘都是比較其引用,因為string是經常需要操作,所以會直接比較其值,所以會對其特殊對待,所以如果遇見特殊的引用型別需要檢視一下是否進行了==過載,預設情況大家都可以把==在比較引用型別時當成比較引用!

下面是關於四種比較的例子:

 class Program
    {
        static void Main(string[] args)
        {
            string personName1 = "張三";
            string personName2 = "李四";

            int age1 = 22;
            int age2 = 22;

            Student Person1, Person2;
            Person1 = new Student(personName1);
            Person2 = new Student(personName2);

            //1.例項Equals() 虛方法,比較引用,可重寫來比較值
            bool b1 = personName1.Equals(personName2);
            bool b2 = age1.Equals(age2);
            bool b3 = Person1.Equals(Person2);
            Console.WriteLine("1.例項Equals()結果:");
            Console.WriteLine("personName1.Equals(personName2) :{0}", b1);
            Console.WriteLine("age1.Equals(age2) :{0}", b2);
            Console.WriteLine("Person1.Equals(Person2) :{0}", b3);

            Console.WriteLine("------------------------------------------------");

            //2.==
            bool b4 = personName1 == personName2;
            bool b5 = age1 == age2;
            bool b6 = Person1 == Person2;

            Console.WriteLine("2.==:");
            Console.WriteLine("personName1 == personName2 :{0}", b4);
            Console.WriteLine("age1 == age2 :{0}", b5);
            Console.WriteLine("Person1 == Person2 :{0}", b6);

            Console.WriteLine("------------------------------------------------");

            //3.ReferenceEquals()
            bool b7 = ReferenceEquals(personName1, personName2);
            bool b8 = ReferenceEquals(age1, age2);
            bool b9 = ReferenceEquals(Person1, Person2);

            Console.WriteLine("3.ReferenceEquals():");
            Console.WriteLine("ReferenceEquals(personName1,personName2) :{0}", b7);
            Console.WriteLine("ReferenceEquals(age1,age2) :{0}", b8);
            Console.WriteLine("ReferenceEquals(Person1,Person2) :{0}", b9);

            Console.WriteLine("------------------------------------------------");

            //4.靜態的Equals()
            bool b10 = Equals(personName1, personName2);
            bool b11 = Equals(age1, age2);
            bool b12 = Equals(Person1, Person2);

            Console.WriteLine("3.Equals():");
            Console.WriteLine("Equals(personName1,personName2) :{0}", b10);
            Console.WriteLine("Equals(age1,age2) :{0}", b11);
            Console.WriteLine("Equals(Person1,Person2) :{0}", b12);


            Console.WriteLine("------------------------------------------------");
            int i = 5;
            float j = 5;
            bool bb = i.Equals(j);//不會進行型別轉換
            bool bb1 = i == j;
            bool bb2 = Equals(i, j);
            Console.WriteLine("i.Equals(j):{0}", bb);
            Console.WriteLine("i==j:{0}", bb1);
            Console.WriteLine("Equals(i,j):{0}", bb2);
            Console.WriteLine();
            Console.ReadKey();
        }

    }
    public class Student
    {
        private string name;
        public Student(string name)
        {
            this.name = name;
        }
        public void ShowName()
        {
            Console.WriteLine(this.name);
        }
    }

執行結果如下: