Сравнение двух экземпляров класса

у меня есть класс такой

public class TestData
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   
}

Я хочу знать, можно ли напрямую сравнивать экземпляры этого класса друг с другом и узнать, что они точно такие же? каков механизм? Я смотрю гор что-то вроде if(testData1 == testData2) //Do Something и если нет, то как это сделать?

7 ответов


вы должны использовать тег IEquatable<T> интерфейс вашего класса, который позволит вам определить вашу логику равенства. На самом деле, вы должны переопределить Equals способ также.

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }   

  // Overriding Equals member method, which will call the IEquatable implementation
  // if appropriate.

   public override bool Equals( Object obj )
   {
       var other = obj as TestData;
       if( other == null ) return false;

       return Equals (other);             
   }

   public override int GetHashcode()
   {
      // Provide own implementation
   }


   // This is the method that must be implemented to conform to the 
   // IEquatable contract

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

       if( ReferenceEquals (this, other) )
       {
            return true;
       }

       // You can also use a specific StringComparer instead of EqualityComparer<string>
       // Check out the specific implementations (StringComparer.CurrentCulture, e.a.).
       if( EqualityComparer<string>.Default.Compare (Name, other.Name) == false )
       {
           return false;
       }
       ...

       // To compare the members array, you could perhaps use the 
       // [SequenceEquals][2] method.  But, be aware that [] {"a", "b"} will not
       // be considerd equal as [] {"b", "a"}

       return true;

   }

}

существует три способа объектов некоторого ссылочного типа T можно сравнить друг с другом:

  1. С object.Equals метод
  2. с осуществлением IEquatable<T>.Equals (только для типов, которые реализуют IEquatable<T>)
  3. с оператором сравнения ==

кроме того, есть две возможности для каждого из этих случаев:

  1. статический тип сравниваемых объектов T (или какая-то другая база T)
  2. статический тип сравниваемых объектов -object

правила, которые вам абсолютно необходимо знать:

  • значение по умолчанию для обоих Equals и operator== это проверить на равенство ссылок
  • реализации Equals будет работать правильно независимо от того, какой статический тип сравниваемых объектов
  • IEquatable<T>.Equals всегда должны вести себя так же, как object.Equals, но если статический тип объектов T он предложит немного лучшую производительность

так что же все это означает на практике?

как правило, вы должны использовать Equals для проверки равенства (переопределение object.Equals при необходимости) и реализовать IEquatable<T> также обеспечить немного лучшую производительность. В этом случае object.Equals должно быть реализовано в терминах IEquatable<T>.Equals.

для некоторых конкретных типов (таких как System.String) также приемлемо использовать operator==, хотя вы должны быть осторожны, чтобы не сделать "полиморфных сравнения". The Equals методы, с другой стороны, будут работать правильно, даже если вы делаете такие сравнения.

вы можете увидеть пример полиморфного сравнения и почему это может быть проблемой здесь.

наконец, никогда не забывайте, что если вы переопределяете object.Equals вы также должны переопределить object.GetHashCode соответственно.


один из способов сделать это-реализовать IEquatable<T>

public class TestData : IEquatable<TestData>
{
   public string Name {get;set;}
   public string type {get;set;}

   public List<string> Members = new List<string>();

   public void AddMembers(string[] members)
   {
      Members.AddRange(members);
   }

   public bool Equals(TestData other)
   {
        if (this.Name != other.Name) return false;
        if (this.type != other.type) return false;

        // TODO: Compare Members and return false if not the same

        return true;
   }
}


if (testData1.Equals(testData2))
    // classes are the same

вы также можете просто переопределить метод Equals(object) (from System.Object), если вы это сделаете, вы также должны переопределить GetHashCode посмотреть здесь


вы можете переопределить метод equals и внутри него вручную сравнить объекты

посмотрите рекомендации по перегрузке Equals () и Operator ==


вам нужно будет определить правила, которые делают объект A равным объекту B, а затем переопределить оператор Equals для этого типа.

http://msdn.microsoft.com/en-us/library/ms173147 (v=против 80).aspx


прежде всего равенство трудно определить, и только вы можете определить, что означает равенство для вас

  1. означает ли это, что члены имеют одинаковое значение
  2. или они указывают на одно и то же место.

вот Обсуждение и ответ здесь

что такое "лучшая практика" для сравнения двух экземпляров ссылочного типа?


реализовать IEquatable<T> interface. Это определяет обобщенный метод, реализуемый типом значения или классом для создания специфичного для типа метода определения равенства экземпляров. Более подробная информация здесь:

http://msdn.microsoft.com/en-us/library/ms131187.aspx