记录为空?
Record is empty?
Delphi的记录类型中是否有任何数据?怎么理解?
例如,假设得到这样的记录类型;
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;
那么,有什么方法可以在不浏览记录项的情况下解决这个问题吗?
使用成员函数
恕我直言,到目前为止最干净的方法是声明一个方法 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;
那你可以随时用这个方法查看记录是否为空:
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;
使用等号运算符
另一种方法:
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;
现在你可以做
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;
疯狂的东西
如果您绝对不想单独比较每个成员,您可以在某些情况下比较字节。
但请注意,一般情况下,您不能通过比较字节来比较两条记录。仅提及两个明显的原因:
字符串成员在语义上可能相等,即使它们由两个不同的字符串堆对象表示(因此比较器说“不相等”,而实际上它们是相等的)。
如果记录不是 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;
但这太疯狂了。
Delphi的记录类型中是否有任何数据?怎么理解?
例如,假设得到这样的记录类型;
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;
那么,有什么方法可以在不浏览记录项的情况下解决这个问题吗?
使用成员函数
恕我直言,到目前为止最干净的方法是声明一个方法 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;
那你可以随时用这个方法查看记录是否为空:
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;
使用等号运算符
另一种方法:
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;
现在你可以做
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;
疯狂的东西
如果您绝对不想单独比较每个成员,您可以在某些情况下比较字节。
但请注意,一般情况下,您不能通过比较字节来比较两条记录。仅提及两个明显的原因:
字符串成员在语义上可能相等,即使它们由两个不同的字符串堆对象表示(因此比较器说“不相等”,而实际上它们是相等的)。
如果记录不是
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;
但这太疯狂了。