Cette question est la suite d'un commentaire de gens sur stackoverflow qui, je l'ai vu quelques fois maintenant. J'ai, avec le développeur qui m'a enseigné à Delphes, dans le but de garder les choses sûr, ont toujours mis un chèque if assigned()
avant de libérer les objets, et avant de faire d'autres choses diverses. Cependant, je me suis dit que je devrais pas être en ajoutant cette case. Je voudrais savoir si il y a une différence dans la façon dont l'application compile/fonctionne si je fais cela, ou si elle n'affecte pas le résultat à toutes les...
if assigned(SomeObject) then SomeObject.Free;
Disons que j'ai un formulaire, et je suis de la création d'un objet bitmap dans le fond sur la forme de la création, et de la libérer quand je suis fait avec elle. Maintenant, je suppose que mon problème est que j'ai trop l'habitude de mettre ce contrôle sur une grande partie de mon code quand j'essaye d'accéder à des objets qui pourraient avoir été libre avais à un certain point. J'ai été de les utiliser même quand il n'est pas nécessaire. J'aime être approfondie...
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.
Maintenant, disons que je suis l'introduction d'une nouvelle liste personnalisée objet appelé TMyList
de TMyListItem
. Pour chaque élément de cette liste de cours que j'ai créer/gratuit chaque élément de l'objet. Il y a quelques différentes façons de créer un élément, ainsi que quelques différentes façons de détruire un élément (Ajout/Suppression d'être le plus commun). Je suis sûr que c'est une très bonne pratique de mettre cette protection ici...
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;
Dans de nombreux scénarios, au moins j'espère que l'objet est toujours créé avant j'ai essayer de le dégager. Mais vous ne savez jamais ce que les feuillets qui pourrait arriver dans le futur où un objet se dégage avais avant qu'il est censé. J'ai toujours utilisé cette case, mais maintenant je me dit que je ne devrais pas, et je ne comprends toujours pas pourquoi.
MODIFIER
Voici un exemple pour essayer de vous expliquer pourquoi j'ai l'habitude de le faire:
procedure TForm1.FormDestroy(Sender: TObject);
begin
SomeCreatedObject.Free;
if SomeCreatedObject = nil then
ShowMessage('Object is nil')
else
ShowMessage('Object is not nil');
end;
Mon point est qu' if SomeCreatedObject <> nil
n'est pas le même que if Assigned(SomeCreatedObject)
car après la libération SomeCreatedObject
, il n'évalue pas à l' nil
. Donc, les deux contrôles nécessaires.