Если вы хотите сравнить два экземпляра пользовательского класса для равенства значений (то есть два объекта с одинаковыми значениями или значениями), а не качество ссылки (что две ссылки на объекты относятся к одному и тому же базовому объекту), вы должны принять это учитывается при проектировании объекта. Существует 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");
Это минимум. Однако, как отмечалось в связанной статье, вы можете рассмотреть следующие оптимизации:
Переопределение virtual Object.Equals(Object)
метод так, что вызывает специфический тип Равно метод. Это позволит вам сравнить MyClass
с объектами других типов:
public override bool Equals(object obj)
{
return this.Equals(obj as MyClass);
}
Добавить в 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);
}
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;
}
}
При желании переопределить ==
и !=
операторов. Если они не будут переопределены, они будут использовать равенство по умолчанию. См. Связанную статью для примера.
Вот мой пример в полном объеме:
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");
}
}
}
Создание иерархии объектов ти * подошва * Цель сравнения ИМХО излишеством. Если они разделяют некоторые другие общие черты поведения/реализации, тогда это может быть разумно, иначе я бы просто реализовал статический метод (расширение или нет, на самом деле не имеет значения), который просто возвращает bool, указывающий, являются ли все 8 свойств двух данных экземпляров тоже самое. – InBetween
Подумал, что я не обращу внимания на наиболее очевидное решение! Вы также хотите увидеть некоторые из моих имен переменных! ;) – user3791372