Итак, вопрос заключается в том, как определить, содержит ли запись (record) в Delphi данные или нет. Предположим, у нас есть тип записи следующего вида:
type
TDummy = PACKED record
Text : String;
Number : Integer;
end;
var
aRecord : TDummy;
begin
aRecord := Default(TDummy); // В этом состоянии "aRecord" не является пустым, так как содержит пустую строку и ноль.
end;
На первый взгляд может показаться, что после инициализации переменной aRecord значением по умолчанию, она будет пустой. Однако это не совсем верно, так как строковое поле Text будет содержать пустую строку, а числовое поле Number — ноль.
Подходы к решению задачи
Использование функции-члена
Самый чистый и предпочтительный способ — это добавить в запись функцию IsEmpty, которая будет возвращать True, если все поля записи имеют значения по умолчанию, или False в противном случае.
type
TDummy = record
Text: string;
Number: Integer;
function IsEmpty: Boolean;
end;
function TDummy.IsEmpty: Boolean;
begin
Result := (Text = '') and (Number = 0);
end;
Теперь, используя эту функцию, можно легко проверить, пуста ли запись:
procedure TForm1.FormCreate(Sender: TObject);
var
D: TDummy;
begin
D := Default(TDummy);
if D.IsEmpty then
ShowMessage('D is empty.');
// Изменяем одно из полей, и теперь запись не пуста.
D.Number := 394;
if D.IsEmpty then
ShowMessage('D is not empty.');
end;
Использование оператора равенства
Другой подход заключается в определении классового оператора равенства для типа записи. Это позволяет сравнивать запись с нулевым состоянием (empty dummy), которое можно определить как константу.
type
TDummy = record
Text: string;
Number: Integer;
class operator Equal(const Left, Right: TDummy): Boolean;
class operator NotEqual(const Left, Right: TDummy): Boolean;
end;
const
EmptyDummy: TDummy = ();
class operator TDummy.Equal(const Left, Right: TDummy): Boolean;
begin
Result := (Left.Text = Right.Text) and (Left.Number = Right.Number);
end;
class operator TDummy.NotEqual(const Left, Right: TDummy): Boolean;
begin
Result := not (Left = Right);
end;
Теперь можно проверить, пуста ли запись, сравнивая её с константой EmptyDummy:
procedure TForm1.FormCreate(Sender: TObject);
var
D: TDummy;
begin
D := Default(TDummy);
if D = EmptyDummy then
ShowMessage('D is empty.');
// Изменяем одно из полей, и теперь запись не пуста.
D.Number := 394;
if D = EmptyDummy then
ShowMessage('Данный код никогда не выполнится, так как D уже не является пустым.');
end;
Сравнение байтов (не рекомендуется)
Если вы действительно не хотите сравнивать поля по отдельности, можно попытаться сравнить записи на уровне байтов. Однако это может быть рискованно и не всегда корректно из-за возможного наличия подзаполнения в записях или использования динамических строк.
Тем не менее, если тип записи packed, то такой способ может сработать для сравнения с нулевым состоянием:
type
TDummy = packed record
Text: string;
Number: Integer;
end;
TZeroRecord<T: record> = record
class function IsZero([Ref] const ARecord: T): Boolean; static;
end;
class function TZeroRecord<T>.IsZero([Ref] const ARecord: T): Boolean;
begin
var DefT := Default(T);
Result := CompareMem(@ARecord, @DefT, SizeOf(T));
end;
Использование этого подхода может быть оправдано в некоторых случаях, но является более экзотическим и потенциально опасным.
Заключение
Лучшим решением будет использование функции-члена IsEmpty для проверки пустоты записи. Это простой, безопасный и гибкий способ, который позволяет легко расширять функциональность записей без риска ошибок, связанных с сравнением байтов или подзаполнением полей.
Задача заключается в определении пустоты записи (record) в Delphi, то есть в проверке наличия данных в записях определенного типа.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.