IEquatable.Equals 是Object.Equals方法的泛型版本

时间:2022-03-27 16:18:14

The implementation of the Equals method is intended to perform a test for equality with another object of type T, the same type as the current object. The Equals method is called in the following circumstances:

In other words, to handle the possibility that objects of a class will be stored in an array or a generic collection object, it is a good idea to implement IEquatable<T> so that the object can be easily identified and manipulated.

两点注意:

1)如果对象需要存储在集合类中,编写这些类时要考虑实现IEquatable<T>.Equals方法以实现判等,实现IComparable<T>接口以实现排序;

2) 集合类中的某些方法例如LinkedList.Find 方法等要利用对象的Equals方法来判断是否相等。

Sample:  观察对象类的Equals, GetHashCode以及operator override

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

public class Person : IEquatable<Person>
{
   private string uniqueSsn;
   private string lName;

   public Person(string lastName, string ssn)
   {
      this.SSN = ssn;
      this.LastName = lastName;
   }

   public string SSN
   {
      get { return this.uniqueSsn; }
      set { 
         if (Regex.IsMatch(value, @"\d{9}"))
            uniqueSsn = String.Format("{0}-(1}-{2}", value.Substring(0, 3), 
                                                     value.Substring(3, 2), 
                                                     value.Substring(5, 4));
         else if (Regex.IsMatch(value, @"\d{3}-\d{2}-\d{4}"))
            uniqueSsn = value;
         else                                                         
            throw new FormatException("The social security number has an invalid format.");
      }       
   }

   public string LastName
   {
      get { return this.lName; }
      set {
         if (String.IsNullOrEmpty(value))
            throw new ArgumentException("The last name cannot be null or empty.");
         else 
            this.lName = value;
      }
   }

   public bool Equals(Person other) 
   {
      if (other == null) 
         return false;

      if (this.uniqueSsn == other.SSN)
         return true;
      else 
         return false;
   }

   public override bool Equals(Object obj)
   {
      if (obj == null) 
         return false;

      Person personObj = obj as Person;
      if (personObj == null)
         return false;
      else    
         return Equals(personObj);   
   }   

   public override int GetHashCode()
   {
      return this.SSN.GetHashCode();
   }

   public static bool operator == (Person person1, Person person2)
   {
      if ((object)person1 == null || ((object)person2) == null)
         return Object.Equals(person1, person2);

      return person1.Equals(person2);
   }

   public static bool operator != (Person person1, Person person2)
   {
      if (person1 == null || person2 == null)
         return ! Object.Equals(person1, person2);

      return ! (person1.Equals(person2));
   }
}


Test :

public class TestIEquatable
{
   public static void Main()
   {
      // Create a Person object for each job applicant.
      Person applicant1 = new Person("Jones", "099-29-4999");
      Person applicant2 = new Person("Jones", "199-29-3999");
      Person applicant3 = new Person("Jones", "299-49-6999");

      // Add applicants to a List object.
      List<Person> applicants = new List<Person>();
      applicants.Add(applicant1);
      applicants.Add(applicant2);
      applicants.Add(applicant3);

       // Create a Person object for the final candidate.
       Person candidate = new Person("Jones", "199-29-3999");
       if (applicants.Contains(candidate))
          Console.WriteLine("Found {0} (SSN {1}).", 
                             candidate.LastName, candidate.SSN);
      else
         Console.WriteLine("Applicant {0} not found.", candidate.SSN);

      // Call the shared inherited Equals(Object, Object) method. 
      // It will in turn call the IEquatable(Of T).Equals implementation.
      Console.WriteLine("{0}({1}) already on file: {2}.",  
                        applicant2.LastName, 
                        applicant2.SSN, 
                        Person.Equals(applicant2, candidate)); 
   }
}
// The example displays the following output: 
//       Found Jones (SSN 199-29-3999). 
//       Jones(199-29-3999) already on file: True.