为什么在访问对象之前我不应该使用“if Assigned()”?

为什么在访问对象之前我不应该使用“if Assigned()”?

这个问题是stackoverflow上人们特别评论的延续,我现在已经看过几次不同的时间了。我和教我Delphi的开发人员一样,为了保证安全,if assigned()在释放对象之前,以及在做其他各种事情之前总是先做检查。但是,我现在被告知我应该添加此支票。我想知道如果我这样做,应用程序编译/运行的方式是否存在任何差异,或者它是否会对结果产生影响...

if assigned(SomeObject) then SomeObject.Free;

假设我有一个表单,我在表单创建时在后台创建一个位图对象,并在完成表单时释放它。现在我想我的问题是,当我试图访问可能在某些时候可能已经免费的对象时,我已经习惯了对我的很多代码进行检查。即使没有必要,我也一直在使用它。我喜欢彻底......

unit Unit1;interfaceuses
  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

现在让我们说我正在引入一个名为TMyList的新自定义列表对象TMyListItem。对于此列表中的每个项目,我当然必须创建/释放每个项目对象。创建项目有几种不同的方法,以及一些销毁项目的不同方法(添加/删除是最常见的)。我确信将这种保护放在这里是一种非常好的做法......

在许多情况下,至少我希望在我尝试释放它之前仍然创建对象。但是你永远不知道未来在对象被释放之前会发生什么样的滑动。我总是使用这张支票,但现在我被告知我不应该这样,而且我仍然不明白为什么。

德玛西亚99
浏览 618回答 3
3回答

Helenr

Free有一些特殊的逻辑:它检查是否Self是nil,如果是这样,它返回而不做任何事情-这样你就可以安全地调用X.Free,即使X是nil。当你编写析构函数时,这很重要 - 大卫在他的答案中有更多的细节。您可以查看源代码Free以了解其工作原理。我没有方便的Delphi源代码,但它是这样的:procedure&nbsp;TObject.Free;begin &nbsp;&nbsp;if&nbsp;Self&nbsp;<>&nbsp;nil&nbsp;then &nbsp;&nbsp;&nbsp;&nbsp;Destroy;end;或者,如果您愿意,可以将其视为等效代码,使用Assigned:procedure&nbsp;TObject.Free;begin &nbsp;&nbsp;if&nbsp;Assigned(Self)&nbsp;then &nbsp;&nbsp;&nbsp;&nbsp;Destroy;end;您可以编写自己的方法来检查if Self <> nil,只要它们是静态(即,不是virtual或dynamic)实例方法(感谢David Heffernan的文档链接)。但是在Delphi库中,Free我所知道的唯一方法是使用这个技巧。因此,Assigned在调用之前,您无需检查变量是否存在Free;&nbsp;它已经为你做到了。这就是为什么建议是调用Free而不是Destroy直接调用的原因:如果你在nil引用上调用了Destroy&nbsp;,你就会遇到访问冲突。
打开App,查看更多内容
随时随地看视频慕课网APP