Использование методов Contains, Remove и IndexOf в TObjectList<T> с пользовательским типом: тонкости и решения
При работе с коллекциями в Delphi, разработчики часто сталкиваются с необходимостью использования методов Contains, Remove и IndexOf для TObjectList<T>, где T - это пользовательский тип. В данной статье мы рассмотрим, как правильно использовать эти методы, основываясь на примере класса TSocket.
Проблема
Разработчик столкнулся с проблемой при использовании методов Contains, Remove и IndexOf для объекта TObjectList<TSocket>. Создав экземпляр пользовательского типа TSocket, он ожидал, что методы будут использовать переопределённую функцию Equals для сравнения объектов, однако результаты работы методов не соответствовали ожиданиям.
Контекст
В примере кода, предоставленном разработчиком, был создан пользовательский тип TSocket, в котором была переопределена функция Equals для сравнения объектов по значению IP-адреса и порта. Однако, несмотря на это, методы Contains, IndexOf и Remove не работали корректно.
Подтверждённый ответ
Основная ошибка разработчика заключалась в предположении, что TObjectList<T> использует функцию Equals для сравнения объектов. На самом деле, по умолчанию, TObjectList<T> использует компаратор, возвращаемый TComparer<T>.Default, который сравнивает указатели на объекты. Так как были созданы два разных объекта TSocket, их указатели отличались, и результаты работы методов были ожидаемыми.
Для изменения поведения по умолчанию необходимо предоставить собственный компаратор, который можно передать через конструктор TObjectList<T>:
TObjectList<TSocket>.Create(TComparer<TSocket>.Construct(
function (const L, R: TSocket): Integer
begin
// Здесь должна быть реализация сравнения.
end
));
Функция сравнения должна возвращать:
Значение меньше нуля, если L меньше R (обычно -1).
Значение больше нуля, если L больше R (обычно 1).
Нулевое значение, если объекты равны.
Если необходимо только проверить объекты на равенство, можно технически использовать компаратор, который возвращает -1 или 1 в случае неравенства, без дополнительного сравнения. Однако, если планируется сортировка списка или поиск в нём, следует реализовать полноценное сравнение.
Альтернативный ответ
В комментариях было отмечено, что использование Equals для сравнения объектов в списках может быть не лучшим подходом, и предложено сосредоточиться на реализации компаратора. Также обсуждалась возможность использования IEqualityComparer, но поскольку TObjectList<T> использует IComparer<T>, использование IEqualityComparer<T> не поддерживается.
Заключение
При работе с TObjectList<T> важно понимать, что по умолчанию используется компаратор, сравнивающий указатели на объекты. Для изменения этого поведения необходимо предоставить собственный компаратор, который будет использовать логику сравнения, соответствующую требованиям задачи. Переопределение функции Equals в пользовательском классе не влияет на поведение методов Contains, Remove и IndexOf без предоставления собственного компаратора.
Разработчик в Delphi столкнулся с некорректной работой методов `Contains`, `Remove` и `IndexOf` в `TObjectList` из-за неправильного понимания использования компаратора объектов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.