|
|||||||
Сравнение собственных классов
Время создания: 02.11.2019 00:36
Текстовые метки: Сравнение, Equals, GetHashCode
Раздел: Компьютер - C#
Запись: Kozlov-AE/Tetra/master/base/1572644218hpdffgf15i/text.html на raw.githubusercontent.com
|
|||||||
|
|||||||
Как известно, в Си-шарп все классы являются наследниками базового класса object. В нем есть три виртуальных метода – ToString, Equals и GetHashCode. В этом уроке мы поговорим с вами о последних двух методах, а также об операторе «==». Скажу сразу, что вопрос разницы между оператором равенства «==» и методом Equals является классическим вопросом на собеседовании на вакансию программиста Си-шарп. Оператор равенства «==» По умолчанию при работе с ссылочными типами данных (все классы кроме string, интерфейсы, делегаты) оператор «==» проверяет равенство ссылок. Он возвращает true, когда обе ссылки указывают на один объект, в противном случае – false. Приведу код, который демонстрирует работу данного оператора с ссылочными типами: static void Main(string[] args) Здесь создается два объекта, ссылки на которые записываются в переменные o1 и o2. Дальше ссылка o1 копируется в переменную o3 (o1 и o3 указывают на один объект). В итоге имеем false при сравнении ссылок o1 и o2, и true при o1 и o3. Метод Equals Метод Equals принимает один аргумент – объект, который будет сравниваться с текущим объектом, и определяет, равны ли между собой эти объекты. Здесь уже идет речь о равенстве полей объектов, а не ссылок. Этот метод виртуальный, и его базовая реализация это просто проверка равенства ссылок оператором «==». Но когда мы создаем некий класс, и нам необходимо реализовать возможность проверки идентичности объектов, следует переопределить именно данный метод, а не воспользоваться перегрузкой оператора «==», чтобы не спутывать базовые назначения этих инструментов сравнивания. Перегрузка метода Equals При переопределении метода Equals следует позаботиться о том, чтобы этот метод возвращал false в случаях, когда в метод передано значение NULL, когда переданный объект нельзя привести к типу текущего объекта, ну и когда поля объектов отличаются. Возьмем уже знакомый нам класс Money с предыдущего урока, и переопределим в нем метод Equals: public class Money Как видим, в коде выше метод Equals и оператор «==» работают соответственно своим базовым определениям. Также для повышения производительности при переопределении метода Equals рекомендуется перегружать его реализацией с типом аргумента соответствующему классу, в котором он переопределяется: public bool Equals(Money obj) // аргумент типа Money Метод GetHashCode Данный метод, как следует из его названия, возвращает хеш-код. Хеш-код это число соответствующее значению объекта. Это число мы получаем в результате работы некоторого метода, который должен обладать следующими свойствами: - он должен возвращать одинаковый хеш-код каждый раз при вызове для одного и того же объекта. - если имеется два равных (эквивалентных) объекта, то хеш-код для них должен быть одинаковым. Только это не означает, что если объекты неравны, то их хеш-коды обязательно будут разными. Метод GetHashCode используется в таких структурах, как хэш-таблицы (Hashtable). Это мы сейчас рассматривать не будем, но корректность их работы стоит обеспечивать. Методы Equals и GetHashCode тесно связанны между собой, при переопределении одного из них, следует переопределять и другой. Базовая реализация метода GetHashCode в классе object очень условная, и она не обеспечивает второе свойство, когда одинаковые объекты имеют одинаковые хеш-коды. static void Main(string[] args) Чтобы это исправить, мы переопределяем метод GetHashCode, и возвращаем хеш-код каким-либо способом, зависящим от поля/полей объекта: public class Money Здесь в качестве хеш-кода возвращается количество денег (целая часть) плюс код валюты. В результате теперь второе условие выполняется. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|