这个问题是从stackoverflow上得来的,关于一个特殊的评论,我在不同的场合下看到过。我以及教我Delphi的开发者,为了保证安全,一直在释放对象之前以及进行其他各种操作之前添加了检查 if assigned()
。但是,现在有人告诉我不应该添加这个检查。我想知道如果我这样做会对应用程序的编译/运行是否有任何影响,或者它不会对结果产生任何影响...
if assigned(SomeObject) then SomeObject.Free;
假设我有一个表单,在表单创建时在后台创建一个位图对象,并在使用完毕后释放它。现在我的问题是,当尝试访问可能已被释放的对象时,我太习惯于在很多代码中放置此检查。即使不必要,我也一直在使用它。我喜欢做到彻底...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FBitmap: TBitmap;
public
function LoadBitmap(const Filename: String): Bool;
property Bitmap: TBitmap read FBitmap;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FBitmap:= TBitmap.Create;
LoadBitmap('C:\Some Sample Bitmap.bmp');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if assigned(FBitmap) then begin //<-----
//Do some routine to close file
FBitmap.Free;
end;
end;
function TForm1.LoadBitmap(const Filename: String): Bool;
var
EM: String;
function CheckFile: Bool;
begin
Result:= False;
//Check validity of file, return True if valid bitmap, etc.
end;
begin
Result:= False;
EM:= '';
if assigned(FBitmap) then begin //<-----
if FileExists(Filename) then begin
if CheckFile then begin
try
FBitmap.LoadFromFile(Filename);
except
on e: exception do begin
EM:= EM + 'Failure loading bitmap: ' + e.Message + #10;
end;
end;
end else begin
EM:= EM + 'Specified file is not a valid bitmap.' + #10;
end;
end else begin
EM:= EM + 'Specified filename does not exist.' + #10;
end;
end else begin
EM:= EM + 'Bitmap object is not assigned.' + #10;
end;
if EM <> '' then begin
raise Exception.Create('Failed to load bitmap: ' + #10 + EM);
end;
end;
end.
现在假设我正在介绍一个新的自定义列表对象,称为TMyList
,其中包含TMyListItem
。当然,对于此列表中的每个项目,我都必须创建/释放每个项目对象。创建项目有几种不同的方法,销毁项目也有几种不同的方法(添加/删除是最常见的)。我相信在这里加入保护措施是一个非常好的实践......
procedure TMyList.Delete(const Index: Integer);
var
I: TMyListItem;
begin
if (Index >= 0) and (Index < FItems.Count) then begin
I:= TMyListItem(FItems.Objects[Index]);
if assigned(I) then begin //<-----
if I <> nil then begin
I.DoSomethingBeforeFreeing('Some Param');
I.Free;
end;
end;
FItems.Delete(Index);
end else begin
raise Exception.Create('My object index out of bounds ('+IntToStr(Index)+')');
end;
end;
在许多情况下,我希望在尝试释放对象之前该对象已经被创建。但是你永远不知道未来会发生什么意外事件,导致一个对象在它应该被释放之前被释放了。我一直使用这种检查方法,但现在有人告诉我不应该这样做,我仍然不明白为什么。
编辑
这里有一个例子,试图向您解释我为什么有这个习惯:
procedure TForm1.FormDestroy(Sender: TObject);
begin
SomeCreatedObject.Free;
if SomeCreatedObject = nil then
ShowMessage('Object is nil')
else
ShowMessage('Object is not nil');
end;
我的观点是,if SomeCreatedObject <> nil
和 if Assigned(SomeCreatedObject)
是不同的,因为在释放 SomeCreatedObject
后,它不会被评估为 nil
。因此,两个检查都应该是必要的。