У меня есть класс Person, и я создал класс сравнения равенства, производный от EqualityComparer ‹ Person >. Тем не менее, EqualityComparer по умолчанию не вызывает функцию Equals моего компаратора равенства
Согласно MSDN EqualityComparer ‹ T > свойство .Default а>:
Свойство Default проверяет, реализует ли тип T интерфейс System.IEquatable, и, если да, возвращает EqualityComparer, использующий эту реализацию. В противном случае он возвращает EqualityComparer, который использует переопределения Object.Equals и Object.GetHashCode, предоставленные T.
В приведенном ниже (упрощенном) примере класс Person не реализует реализацию System.IEquatable ‹ Person >. Поэтому я ожидаю, что PersonComparer.Default вернет экземпляр PersonComparer.
Однако PersonComparer.Equals не вызывается. Выходные данные отладки отсутствуют, а возвращаемое значение ложно.
public class Person
{
public string Name { get; set; }
}
public class PersonComparer : EqualityComparer<Person>
{
public override bool Equals(Person x, Person y)
{
Debug.WriteLine("PersonComparer.Equals called");
return true;
}
public override int GetHashCode(Person obj)
{
Debug.WriteLine("PersonComparer.GetHasCode called");
return obj.Name.GetHashCode();
}
}
public static void Main()
{
Person x = new Person() { Name = "x" };
Person y = new Person() { Name = "x" };
bool b1 = PersonComparer.Default.Equals(x, y);
}
Вопрос: что я делаю не так?
На случай, если вы спросите, почему я не хочу реализовывать IEquatable ‹ Person >.
Моя проблема сравнима со сравнением строк. Иногда вы хотите, чтобы две строки были равны, если они являются абсолютно одинаковыми строками, иногда вы хотите игнорировать регистр, а иногда вы хотите обрабатывать символы как óò и т. д., как если бы они были символом o.
В моем случае: я храню Person в чем-то, что может быть базой данных, но это также может быть файл или поток памяти. По возвращении я получаю идентификатор, который в случае базы данных, конечно же, является первичным ключом. С помощью этого ключа я могу получить объект с теми же значениями.
Я хочу проверить это в модульном тесте: если вы что-то поместите в него, вы должны получить ключ, который можно использовать для извлечения элемента. Увы, база данных возвращает не того же человека, а производный от него класс (по крайней мере, при использовании EF 6). Поэтому я не могу использовать обычный IEquatable, который должен возвращать false, если объекты не одного типа. Вот почему я хотел использовать специальный компаратор, который объявляет два класса Person равными, если они имеют одинаковые значения свойств, даже если они оба являются разными производными классами от Person. Очень сопоставим как компаратор строк, который принимает O и o и ó равными
Equals(object)
иGetHashCode
дляPerson
. Как вы думаете, почему он будет использоватьPersonComparer
? - person Lee   schedule 26.11.2015new PersonComparer()
вместоPersonComparer.Default.
. - person Dennis_E   schedule 26.11.2015Person
должно делать само по себе и которое, следовательно, будет использоватьEqualityComparer<Person>.Default
. - person Jon Hanna   schedule 26.11.2015