2015-11-19 2 views
0

У меня есть класс с десятью свойствами, и я ищу объекты, которые имеют одинаковые значения в этих свойствах, за исключением двух конкретных свойств.Определить, являются ли два экземпляра одинаковыми, за исключением двух свойств.

Я думаю о расширении базового класса, который имеет восемь свойств, которые я хочу сравнить, а затем расширить этот базовый класс, вызвав базовый метод Equals?

Что было бы наименее понятным для кода способом определения этого?

+3

Создание иерархии объектов ти * подошва * Цель сравнения ИМХО излишеством. Если они разделяют некоторые другие общие черты поведения/реализации, тогда это может быть разумно, иначе я бы просто реализовал статический метод (расширение или нет, на самом деле не имеет значения), который просто возвращает bool, указывающий, являются ли все 8 свойств двух данных экземпляров тоже самое. – InBetween

+0

Подумал, что я не обращу внимания на наиболее очевидное решение! Вы также хотите увидеть некоторые из моих имен переменных! ;) – user3791372

ответ

0

Если вы хотите сравнить два экземпляра пользовательского класса для равенства значений (то есть два объекта с одинаковыми значениями или значениями), а не качество ссылки (что две ссылки на объекты относятся к одному и тому же базовому объекту), вы должны принять это учитывается при проектировании объекта. Существует pattern you can follow to do this. Вкратце, это предполагает реализацию интерфейса System.IEquatable<T>, который определяет метод с сигнатурой bool Equals(MyClass other). Вы реализуете этот метод для возврата true, когда other имеет такое же значение, что и объект this. Вот простой пример ofsimple объект, который имеет 4 свойства, которые определяют его значение равенства:

class MyClass : IEquatable<MyClass> 
{ 
    public int ImportantProperty1 { get; set; } 
    public int ImportantProperty2 { get; set; } 
    public int ImportantProperty3 { get; set; } 
    public int ImportantProperty4 { get; set; } 
    public int NonImportantProperty { get; set; } 

    public bool Equals(MyClass other) 
    { 
     return 
      (!Object.ReferenceEquals(this, null)) && 
      (this.ImportantProperty1 == other.ImportantProperty1) && 
      (this.ImportantProperty2 == other.ImportantProperty2) && 
      (this.ImportantProperty3 == other.ImportantProperty3) && 
      (this.ImportantProperty4 == other.ImportantProperty4); 
    } 
} 

С выше кода вы сможете сделать следующее:

MyClass a = new MyClass() { }; 
MyClass b = new MyClass() { }; 
if (a.Equals(b)) 
    Console.WriteLine("a and b are equal"); 

Это минимум. Однако, как отмечалось в связанной статье, вы можете рассмотреть следующие оптимизации:

  1. Переопределение virtual Object.Equals(Object) метод так, что вызывает специфический тип Равно метод. Это позволит вам сравнить MyClass с объектами других типов:

    public override bool Equals(object obj) 
    { 
        return this.Equals(obj as MyClass); 
    } 
    
  2. Добавить в bool Equals(MyClass) методе проверки, чтобы увидеть, если other ссылается на тот же объект, как this:

    public bool Equals(MyClass other) 
        { 
         if (Object.ReferenceEquals(this, other)) 
          return true;  
    
         return 
          (!Object.ReferenceEquals(this, null)) && 
          (this.ImportantProperty1 == other.ImportantProperty1) && 
          (this.ImportantProperty2 == other.ImportantProperty2) && 
          (this.ImportantProperty3 == other.ImportantProperty3) && 
          (this.ImportantProperty4 == other.ImportantProperty4); 
        } 
    
  3. Override Object.GetHashCode() метод так что два объекта, имеющих равенство значений, производят один и тот же хэш-код. Это шаблон использовать при реализации этого метода в этом виде сценария:

    public override int GetHashCode() 
    { 
        unchecked { 
         int hash = 17; 
         hash = hash * 23 + ImportantProperty1.GetHashCode(); 
         hash = hash * 23 + ImportantProperty2.GetHashCode(); 
         hash = hash * 23 + ImportantProperty3.GetHashCode(); 
         hash = hash * 23 + ImportantProperty4.GetHashCode(); 
         return hash; 
        } 
    } 
    
  4. При желании переопределить == и != операторов. Если они не будут переопределены, они будут использовать равенство по умолчанию. См. Связанную статью для примера.

Вот мой пример в полном объеме:

namespace ValueEquality 
{ 

    class MyClass : IEquatable<MyClass> 
    { 
     public int ImportantProperty1 { get; set; } 
     public int ImportantProperty2 { get; set; } 
     public int ImportantProperty3 { get; set; } 
     public int ImportantProperty4 { get; set; } 
     public int NonImportantProperty { get; set; } 

     public bool Equals(MyClass other) 
     { 
      if (Object.ReferenceEquals(this, other)) 
       return true;  

      return 
       (!Object.ReferenceEquals(this, null)) && 
       (this.ImportantProperty1 == other.ImportantProperty1) && 
       (this.ImportantProperty2 == other.ImportantProperty2) && 
       (this.ImportantProperty3 == other.ImportantProperty3) && 
       (this.ImportantProperty4 == other.ImportantProperty4); 
     } 

     public override bool Equals(object obj) 
     { 
      return this.Equals(obj as MyClass); 
     } 

     public override int GetHashCode() 
     { 
      unchecked { 
       int hash = 17; 
       hash = hash * 23 + ImportantProperty1.GetHashCode(); 
       hash = hash * 23 + ImportantProperty2.GetHashCode(); 
       hash = hash * 23 + ImportantProperty3.GetHashCode(); 
       hash = hash * 23 + ImportantProperty4.GetHashCode(); 
       return hash; 
      } 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyClass a = new MyClass() { }; 
      MyClass b = new MyClass() { }; 
      if (a.Equals(b)) 
       Console.WriteLine("a and b are equal"); 
     } 
    } 
} 
Смежные вопросы