gpt4 book ai didi

delphi - 已分配 vs <> nil

转载 作者:行者123 更新时间:2023-12-03 14:33:45 25 4
gpt4 key购买 nike

If Assigned(Foo)有什么区别吗和 If (Foo <> nil) ?如果是,它们应该在什么时候使用?

最佳答案

TL;博士
The official documentation状态

Assigned(P) corresponds to the test P <> nil for a pointer variable, and @P <> nil for a procedural variable.


因此,对于非过程指针变量(例如类型为 PIntegerPMyRecTBitmapTList<integer>TFormClass 的变量), Assigned(P)P <> nil 是一样的.
但是,对于过程变量, Assigned(P)@P <> nil 是一样的, 而 P <> nil会尝试执行 P 的过程或函数指向(带有空参数列表)。
说明
上面的文档摘录很好地总结了它。 Assigned(X)返回 True当且仅当 X变量,它必须是引擎盖下的指针(有一些异常(exception)),具有非 nil值(value)。 Assigned可用于“老派”指针变量:
var
i: Integer;
p: PInteger;
begin
i := 5;

p := @i;
{ Assigned(p) True }
{ p <> nil True }

p := nil;
{ Assigned(p) False }
{ p <> nil False }
Assigned也可以用于对象(和元类)变量。事实上,在 Delphi 中,对象(或元类)变量只是引擎盖下的一个指针:
L := TList<integer>.Create;
try
{ Assigned(L) True }
{ L <> nil True }
finally
FreeAndNil(L);
end;

{ Assigned(L) False }
{ L <> nil False }
(并且,为了完整起见,还有一个带有元类变量的示例:
var
FC: TFormClass;
begin

FC := TForm;
{ Assigned(FC) True }
{ FC <> nil True }

FC := nil;
{ Assigned(FC) False }
{ FC <> nil False }
)
在所有这些示例中, Assigned(X)X <> nil完全一样.
但是,对于过程类型,情况略有不同。
首先,让我们热身:
type
TStringProc = procedure(const AText: string);

procedure MyStrProc(const AText: string);
begin
ShowMessage(AText);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
SP: TStringProc;
begin
SP := MyStrProc;
SP('test');
end;
特别注意 SP用于实际调用它当前指向的过程。
现在,你可以试试
procedure TForm1.FormCreate(Sender: TObject);
var
SP: TStringProc;
begin
SP := MyStrProc;
ShowMessage(BoolToStr(Assigned(SP), True)); { True }
ShowMessage(BoolToStr(SP <> nil, True)); { will not compile }

SP := nil;
ShowMessage(BoolToStr(Assigned(SP), True)); { False }
ShowMessage(BoolToStr(SP <> nil, True)); { will not compile }
end;
但这甚至不会编译。编译器说,“没有足够的实际参数”。原因是上面的代码会尝试执行 SP的过程。指向,然后确实需要 AText缺少参数。 (当然,在编译时,编译器不知道 SP 是否会指向兼容的过程,但它确实知道这样一个有效过程的签名。)
即使过程类型有一个空参数列表,它也不会编译,因为过程不返回值(更不用说可以与 nil 进行比较的值)。
但要小心!以下代码将编译:
type
TGetPtrFunc = function: pointer;

function MyPtrFunc: pointer;
begin
Result := nil;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
PF: TGetPtrFunc;
begin
PF := MyPtrFunc;
ShowMessage(BoolToStr(Assigned(PF), True)); { True }
ShowMessage(BoolToStr(PF <> nil, True)); { False (!) }

PF := nil;
ShowMessage(BoolToStr(Assigned(PF), True)); { False }
ShowMessage(BoolToStr(PF <> nil, True)); { will cause access violation at runtime }
end;
第一 PF <> nil将比较 MyPtrFunc函数结果值对 nil ;它会 不是 告诉你是否 PF函数指针是否被赋值(它是!)。
第二个 PF <> nil将尝试调用 nil函数指针;这是一个错误(访问冲突异常)。
要测试是否分配了过程变量,您必须测试 @PF <> nil :
procedure TForm1.FormCreate(Sender: TObject);
var
SP: TStringProc;
begin
SP := MyStrProc;
ShowMessage(BoolToStr(Assigned(SP), True)); { True }
ShowMessage(BoolToStr(@SP <> nil, True)); { True }

SP := nil;
ShowMessage(BoolToStr(Assigned(SP), True)); { False }
ShowMessage(BoolToStr(@SP <> nil, True)); { False }
end;

procedure TForm1.FormCreate(Sender: TObject);
var
PF: TGetPtrFunc;
begin
PF := MyPtrFunc;
ShowMessage(BoolToStr(Assigned(PF), True)); { True }
ShowMessage(BoolToStr(@PF <> nil, True)); { True }

PF := nil;
ShowMessage(BoolToStr(Assigned(PF), True)); { False }
ShowMessage(BoolToStr(@PF <> nil, True)); { False }
end;
对于过程变量, Assigned(X)@X <> nil 是一样的,如文档所述。
方法
就本主题而言,方法作为常规程序起作用。例如,对于方法变量 M , Assigned(M)相当于 @M <> nil并且是 True如果方法指针不是 nil . (在幕后,我相信 @M 产生 Code 成员 TMethod 。)
procedure TForm1.FormCreate(Sender: TObject);
var
M: TNotifyEvent;
begin
M := Self.FormClick;
ShowMessage(BoolToStr(Assigned(M), True)); { True }
ShowMessage(BoolToStr(@M <> nil, True)); { True }

M := nil;
ShowMessage(BoolToStr(Assigned(M), True)); { False }
ShowMessage(BoolToStr(@M <> nil, True)); { False }
end;
用什么?
所以,你应该使用 Assigned(X)X <> nil对于非程序指针?你应该使用 Assigned(X)@X <> nil对于程序指针?这完全是一个品味问题。
就个人而言,我倾向于使用 Assigned(X)当我想测试变量是否已分配时, X = nil (或 @X = nil )当我想测试变量是否未分配时,仅仅是因为 not Assigned(X)不那么紧凑。
相关警告
当然,两者都是 Assigned(X)X <> nil (或 @X <> nil )仅测试指针是否为 nil或不;如果非 nil ,指针可能仍指向垃圾。例如,由于本地非托管变量在 Delphi 中没有初始化,它们很可能是非 nil在它们被赋值之前,但在这种情况下,它们指向垃圾:
procedure TForm1.FormCreate(Sender: TObject);
var
L: TList<integer>; { local non-managed variable: not initialized }
begin
Assigned(L) { True or False (chance). If True, it points to garbage data. }
{ Bad things will happen if you try to use L as a list here }
{ (especially if L is not nil). }
另一个例子:
  L := TList<integer>.Create;
try
{ Do things with L }
finally
L.Free;
end;

Assigned(L); { True, but L points to garbage -- don't use it as a list! }

关于delphi - 已分配 vs <> nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4484002/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com