EqualityComparer <T>. Непонимание по умолчанию? - PullRequest
5 голосов
/ 11 марта 2012

У меня есть класс 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. Может кто-нибудь дать мне пример, чтобы доказать, что я не прав?

Ответы [ 3 ]

1 голос
/ 11 марта 2012

То, что вы можете передать в IEqualityComparer<object>.Default, является эффектом универсальной контрастности , добавленной в .NET 4.

По существу, IEqualityComparer<BaseType> может использоваться всякий раз, когда требуется IEqualityComparer<DerivedType>, где DerivedType : BaseType. Поскольку Person происходит от Object, это означает, что IEqualityComparer<Object> может использоваться везде, где требуется IEqualityComparer<Person>.

1 голос
/ 11 марта 2012

Если вы передадите null в качестве второго параметра или если вы вообще не передадите второй аргумент (который в основном совпадает), реализация SequenceEquals сама вызовет EqualityComparer<T>.Default (декомпилировать Enumerable чтобы увидеть это). Это объясняет, почему вы не видите разницы, предоставляете ли вы EqualityComparer<T>.Default или нет.

Таким образом, в конце второй параметр имеет смысл, только если вы хотите использовать средство сравнения равенства , отличное от EqualityComparer<T>.Default.

0 голосов
/ 25 сентября 2014

Ответ здесь: 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 позаботится об этом за вас.

...