Ответ
Да, но механизм и результат сравнения зависят от типа объекта и реализации методов сравнения.
Основные способы сравнения:
- Операторы
==и!= - Метод
object.Equals() - Метод
object.ReferenceEquals()
Поведение по типам:
1. Ссылочные типы (классы):
По умолчанию == и Equals() (без переопределения) сравнивают ссылки, а не содержимое объектов.
class Person { public string Name; }
var person1 = new Person { Name = "Alice" };
var person2 = new Person { Name = "Alice" };
var person3 = person1;
Console.WriteLine(person1 == person2); // False (разные ссылки)
Console.WriteLine(person1.Equals(person2)); // False (разные ссылки)
Console.WriteLine(person1 == person3); // True (одинаковые ссылки)
Для сравнения по значению необходимо переопределить Equals() и GetHashCode(), а также операторы ==/!=.
2. Значимые типы (структуры):
Для struct метод Equals() по умолчанию сравнивает значения всех полей (через рефлексию, что медленно). Оператор == для структур по умолчанию не определён.
public struct Point { public int X, Y; }
var p1 = new Point { X = 1, Y = 2 };
var p2 = new Point { X = 1, Y = 2 };
Console.WriteLine(p1.Equals(p2)); // True (значения полей равны)
// Console.WriteLine(p1 == p2); // Ошибка компиляции: оператор == не определён
Рекомендации для кастомного сравнения:
- Реализуйте интерфейс
IEquatable<T>для типобезопасного и эффективного сравнения. - Всегда переопределяйте
GetHashCode()согласованно сEquals(). - Для ссылочных типов рассмотрите перегрузку операторов
==и!=. - Используйте
ReferenceEquals()для явной проверки ссылочной идентичности.
public class Product : IEquatable<Product>
{
public int Id { get; set; }
public string Name { get; set; }
public bool Equals(Product other)
{
if (other is null) return false;
return Id == other.Id && Name == other.Name;
}
public override bool Equals(object obj) => Equals(obj as Product);
public override int GetHashCode() => HashCode.Combine(Id, Name);
}