Recordisempty?
Is there any data in a Record Type with Delphi? How is it understood?
For example, supposedly get a Record Type like this;
type
TDummy = PACKED record
Text : String;
Number : Integer;
end;
var
aRecord : TDummy;
begin
aRecord := default(TDummy); // In this state "aRecord" is empty. (Text = '' and Number = 0)
aRecord.Text := 'TEST'; // This is no longer empty
end;
So is there any way to figure out this without browsing through the Record Items?
回答
Using a member function
By far the cleanest approach, IMHO, is to declare a method TDummy.IsEmpty: Boolean:
type
TDummy = record
Text: string;
Number: Integer;
function IsEmpty: Boolean;
end;
{ TDummy }
function TDummy.IsEmpty: Boolean;
begin
Result := (Text = '') and (Number = 0);
end;
Then you can always use this method to see if the record is empty:
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 empty.');
end;
Using the equals operator
A different approach:
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 = ();
{ 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;
Now you can do
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 is empty.');
end;
Crazy stuff
If you absolutely do not want to compare each member separately, you can under some circumstances compare the bytes.
但请注意,一般情况下,不能通过比较字节来比较两条记录。只提两个明显的原因:
-
字符串成员在语义上可能是相等的,即使它们由两个不同的字符串堆对象表示(因此比较器说“不相等”而实际上它们是相等的)。
-
如果记录
packed不相同,则记录可能有填充(因此比较器可能会说“不相等”,而实际上它们相等)。
但是您只想与“默认”(归零)值进行比较,并且作为奖励,您的记录类型恰好是packed,因此您可以逃脱
type
TDummy = packed record
Text: string;
Number: Integer;
end;
TZeroRecord<T: record> = record
class function IsZero([Ref] const ARecord: T): Boolean; static;
end;
{ TZeroRecord<T> }
class function TZeroRecord<T>.IsZero([Ref] const ARecord: T): Boolean;
begin
var DefT := Default(T);
Result := CompareMem(@ARecord, @DefT, SizeOf(T));
end;
和
procedure TForm1.FormCreate(Sender: TObject);
var
D: TDummy;
begin
D := Default(TDummy);
if TZeroRecord<TDummy>.IsZero(D) then
ShowMessage('D is empty.');
D.Number := 394;
if TZeroRecord<TDummy>.IsZero(D) then
ShowMessage('D is empty.');
end;
但这相当疯狂。