Страницы

Поиск по вопросам

среда, 3 октября 2018 г.

Зачем мы реализовываем IEquatable, если Equals() есть в Object?

Разбирая тему обобщений (по Шиелду 4.0), потребовалось написать обобщённый метод, который вернет логическое значение true, если в массиве содержится некоторое значение. Далее в книге поясняется, что так как T - обобщённый тип, то для сравнения объектов обобщённого типа необходимо что бы класс этих объектов реализовывал интерфейс IEquatable с параметром T или IEquatable. Написано так же, что в данных интерфейсах определен метод для сравнения Equals(). Отсюда сразу же несколько вопросов:
Во-первых, почему для сравнения объектов обобщённого типа нам вообще необходимо реализовывать какие-либо интерфейсы? Метод Equals() относится к методам определённым в Object => есть в каждом объекте. Я понял что для сравнения объектов в данном примере нужно реализовать описанные выше интерфейсы, но я не понял, ПОЧЕМУ это нужно сделать.
Во-вторых, по Шиелду, как я написал выше, для сравнения объектов в обобщённом методе предлагается реализовать Equtable с параметром T или IEqutable. Один параметризирован, другой нет. Вопрос - какой в каком случае необходимо использовать?
Далее Шиелд в своей книге демонстрирует пример метода, который проверяет, находится ли в массиве некоторое значение. Вот этот метод:
public static bool IsIn(T what, T[] obs) where T : IEquatable { foreach(T v in obs) { if (v.Equals(what)) { return true; } else { return false; } } }
Тут так же есть два вопроса.
Во-первых, начну с того, что данный метод не работает. Студия выдает ошибку компиляции "Не все ветви метода возвращают значение". Я несколько раз перепроверял написанный код, но ошибка остается. Как это исправить?
Во-вторых, я не уверен, правильно ли я понял, что сигнатура данного метода подразумевает, что в данный метод могут быть переданы только объекты тех типов, которые реализовывают интерфейс IEquatable? Другими словами, если я захочу передать в метод массив каких нибудь студентов, и найти в нём Васю Пупкина, то мой класс студента должен выглядить следующим образом?
class Student : IEquatable { public string Name; public string Surname;
public bool Equals(T other) { //some code for compare return false; } }
Прошу последовательно ответить на все вопросы. Спасибо


Ответ

Equals(object obj) появился в .NET в самом начале, а тогда еще не было дженериков. До введения дженериков в .NET 2.0, переопределение метода Equals(object obj) в большинстве случаев выглядело приблизительно так:
public bool override Equals(object obj) { if (obj == null) return false; if (obj is MyClass) { MyClass other = (MyClass)obj; // сравниваем this и other } return false; }
Получается, в большинстве случаев, объекты разных типов не могут быть равны. Что бы упростить жизнь, придумали интерфейс IEquatable, в котором можно сразу сравнивать 2 объекта, без проверок их типов (что тоже занимает некоторое время).
По-хорошему теперь вы должны реализовать IEquatable для всех классов, которые можно сравнивать. При этом вы должны не забывать про переопределение старого Equals, для совместимости. Можно делать например вот так:
public bool override Equals(object obj) { return Equals(obj as MyClass); }
public bool Equals(MyClass other) { if (other== null) return false; // сравниваем объекты }

Комментариев нет:

Отправить комментарий