EqualityComparer<T>.Недоразумение по умолчанию?
-
11-12-2019 - |
Вопрос
у меня есть класс Person
, он реализует метод Equals() из IEquatable<Person>
(также переопределяет Object.Equals
метод, давайте пока проигнорируем метод GetHashcode())
class Person : IEquatable<Person>
{
public string Name { get; set; }
public bool Equals(Person other)
{
return this.Name == other.Name;
}
public override bool Equals(object obj)
{
var person = obj as Person;
return person != null && person.Name == Name;
}
}
Хорошо, давайте начнем:
Person p1 = new Person() { Name = "a" };
Person p2 = new Person() { Name = "a" };
List<Person> lst1 = new List<Person>() { p1 };
List<Person> lst2 = new List<Person>() { p2 };
Давайте поговорим об этой строке:
bool b = lst1.SequenceEqual(lst2, EqualityComparer<Person>.Default);
У меня проблема с пониманием этой части:
EqualityComparer<Person>.Default
я это слышал EqualityComparer<Person>.Default
проверит, реализует ли класс IEquatable
- это займет Equals(Person other)
Метод, а не Equals(object obj)
. у него есть то преимущество, что он позволяет избежать бокса
но
тот Equals(Person other)
побежит с или без EqualityComparer<Person>.Default
(потому что он реализует IEquatable)
Так о каком боксе речь?нет!
Единственный раз, когда Equals(object obj)
будет работать, когда:
bool b = lst1.SequenceEqual(lst2,EqualityComparer<Object>.Default);
Но Я программист!Я никогда не отправлю object
когда это на самом деле Person
!
Что мне не хватает?Мне трудно понять преимущества EqualityComparer<Object>.Default
.Может кто-нибудь привести мне пример, подтверждающий мою неправоту?
Решение
Если вы пройдете null
в качестве второго параметра или если вы вообще не передаете второй аргумент (что по сути то же самое), реализация SequenceEquals вызовет EqualityComparer<T>.Default
сам (декомпилировать Enumerable
чтобы увидеть это).Это объясняет, почему вы не видите разницы, предоставляете ли вы EqualityComparer<T>.Default
или нет.
Таким образом, второй параметр имеет смысл только в том случае, если вы хотите использовать компаратор равенства. Кроме как EqualityComparer<T>.Default
.
Другие советы
Что ты можешь пройти IEqualityComparer<object>.Default
является эффектом родовая контравариантность, добавленный в .NET 4.
По сути, IEqualityComparer<BaseType>
может использоваться всякий раз, когда IEqualityComparer<DerivedType>
требуется, где DerivedType : BaseType
.С Person
происходит от Object
, это означает, что IEqualityComparer<Object>
можно использовать везде, где IEqualityComparer<Person>
требуется.
Ответ здесь: http://msdn.microsoft.com/en-us/library/ms131187(v=vs.110).aspx
Для типа значения всегда следует реализовать IEquatable и переопределить Object.Equals(Object) для повышения производительности.Object.Equals блокирует типы значений и использует отражение для сравнения двух значений на предмет равенства.И ваша реализация Equals, и переопределение Object.Equals должны возвращать согласованные результаты.
Если вы не переопределяете Equals и GetHashCode, EqualityComparer.Default фактически позаботится об этом за вас.