Вопрос

у меня есть класс 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). у него есть то преимущество, что он позволяет избежать бокса

enter image description here но

тот 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 : BaseTypePerson происходит от 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 фактически позаботится об этом за вас.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top