Почему ваши объекты в TList<> ведут себя как один: разбираемся с проблемами class var в Delphi
При работе с генерическими списками в Delphi может возникнуть ситуация, когда все элементы списка содержат одинаковые данные, несмотря на то, что при их добавлении в список использовались различные значения. Это может быть связано с неправильным использованием модификаторов доступа в записях (records), и в частности, с использованием class var. В данной статье мы рассмотрим, как правильно работать с генерическими списками и записями в Delphi, чтобы избежать подобных проблем.
Проблема с class var в записях
Вопрос пользователя заключается в том, что при добавлении записей в генерический список TList<> все элементы списка получают значения последней добавленной записи. Это происходит из-за использования class var для полей записи, что приводит к тому, что все экземпляры записи ссылаются на одни и те же переменные класса, а не на отдельные копии полей.
Пример кода с использованием class var
type
TCompInfo = record
private
class var
FCompanyName : string;
FCompanyPath : string;
FCompanyDataPath: string;
FCompanyVer : string;
public
class procedure Clear; static;
class property CompanyName : string read FCompanyName write FCompanyName;
// Другие свойства...
end;
Решение проблемы
Чтобы каждый элемент списка содержал уникальные данные, необходимо использовать обычные поля записи вместо class var. Каждый экземпляр записи должен иметь свои собственные копии полей.
Пример исправленного кода
type
TCompInfo = record
private
FCompanyName : string;
FCompanyPath : string;
FCompanyDataPath: string;
FCompanyVer : string;
public
property CompanyName : string read FCompanyName write FCompanyName;
// Другие свойства...
end;
Добавление записей в TList<>
После исправления определения записи, добавление записей в список TList<> будет выглядеть следующим образом:
var
CompData: TCompInfo;
AList: TList<TCompInfo>;
// ...
tlCompanyList.GotoBOF;
for i := 0 to tlCompanyList.Count-1 do
begin
if colCompanyChecked.Value then
begin
inc(ItemsChecked);
CompData.CompanyName := colCompanyName.Value;
// Заполнение других полей...
AList.Add(TCompInfo.Create); // Создание нового экземпляра записи
with AList.Items[High(AList)] do // Получение последнего добавленного элемента
begin
CompanyName := CompData.CompanyName;
// Копирование значений полей...
end;
end;
end;
Заключение
Использование class var в записях может привести к непреднамеренному общему доступу к полям всех экземпляров записи. Чтобы избежать этого, следует использовать обычные поля и явно копировать значения при добавлении записей в список. Это обеспечит независимость данных между элементами списка и предотвратит возникновение описанной в вопросе проблемы.
Проблема заключается в том, что при использовании `class var` в записях Delphi, все экземпляры записи делятся общими переменными класса, что приводит к тому, что изменения в одном экземпляре отражаются на всех, что может быть нежелательно при работе с ге
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.