質問

こんにちはうな入れ子にしてみ&つ諸表ント?

var cds1  : TClientDataSet;
    cds2  : TClientDataSet;
    cds3  : TClientDataSet;
    cds4  : TClientDataSet;
begin
  cds1      := TClientDataSet.Create(application );
  try
    cds2      := TClientDataSet.Create(application );
    try
      cds3      := TClientDataSet.Create(application );
      try
        cds4      := TClientDataSet.Create(application );
        try
        ///////////////////////////////////////////////////////////////////////
        ///      DO WHAT NEEDS TO BE DONE
        ///////////////////////////////////////////////////////////////////////
        finally
          cds4.free;
        end;

      finally
        cds3.free;
      end;
    finally
      cds2.free;
    end;
  finally
    cds1.free;
  end;
end;

宜しくお願い致しますのより良い方法?

役に立ちましたか?

解決

どのように以下のもの:

var cds1  : TClientDataSet;
    cds2  : TClientDataSet;
    cds3  : TClientDataSet;
    cds4  : TClientDataSet;
begin
  cds1      := Nil;
  cds2      := Nil;
  cds3      := Nil;
  cds4      := Nil;
  try
    cds1      := TClientDataSet.Create(nil);
    cds2      := TClientDataSet.Create(nil);
    cds3      := TClientDataSet.Create(nil);
    cds4      := TClientDataSet.Create(nil);
    ///////////////////////////////////////////////////////////////////////
    ///      DO WHAT NEEDS TO BE DONE
    ///////////////////////////////////////////////////////////////////////
  finally
    freeandnil(cds4);
    freeandnil(cds3);
    freeandnil(cds2);
    freeandnil(Cds1);
  end;
end;

これについては、次のとおりでありコンパクト、みによる無料のインスタンスが作成されます。ありがする必要はありませんの巣から失敗に落とし、最後に行うすべての清掃活動の例では、お客様よりご提供いただいた.

個人的にはないようにしている巣内と同様の方法...を除いてみ/try/以外の/最後にシナリオ。を発見した場合は自分が必要な巣に、私が考えるリファクタリングにもう一つの方法。

編集 清掃、サンフランシスコへのコメント mghieutku.

編集 変更のオブジェクトを生成しない参考用として必要なことの一例です。

他のヒント

いいものを使っておけば間違いないようになります:

var
  Safe: IObjectSafe;
  cds1 : TClientDataSet;
  cds2 : TClientDataSet;
  cds3 : TClientDataSet;
  cds4 : TClientDataSet;
begin
  Safe := ObjectSafe;
  cds1 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
  cds2 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
  cds3 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
  cds4 := Safe.Guard(TClientDataSet.Create(nil)) as TClientDataSet;
  ///////////////////////////////////////////////////////////////////////
  ///      DO WHAT NEEDS TO BE DONE
  ///////////////////////////////////////////////////////////////////////

  // if Safe goes out of scope it will be freed and in turn free all guarded objects
end;

の実装インタフェースの参照 この ですが、使えます。

編集:

私がこのリンク第ガード()である。自分のコードかマルチガード()関数を返すTObjectは、上記サンプルコード想定しています。のコージェネリック医薬品より良いコードが可能になり...

編集2:

だかってみてはいかがでしょうか...最後には完全に削除され自分のコード:することはできないremoveメソッドは、入れ子のブロックを導入することなく、可能性のメモリリークがdestructorsには例外)にアクセス違反に対するそのために、使用のヘルパークラスのリファレンスカウンターインタフェースを継す。のヘルパークラススペースを確保することが可能ですべてのオブジェクトでガードの場合でも、一部のdestructorsを上げることができます。

ネストされた試しのないコードの別のバリエーションがあります...最終的にそれはちょうど私に起こりました。あなたはnilに設定され、コンストラクタのAOwnerパラメータを使用してコンポーネントを作成しない場合は、単にVCLが自由のためにあなたを与えることを生涯の管理を利用することができます:

var
  cds1: TClientDataSet;
  cds2: TClientDataSet;
  cds3: TClientDataSet;
  cds4: TClientDataSet;
begin
  cds1 := TClientDataSet.Create(nil);
  try
    // let cds1 own the other components so they need not be freed manually
    cds2 := TClientDataSet.Create(cds1);
    cds3 := TClientDataSet.Create(cds1);
    cds4 := TClientDataSet.Create(cds1);

    ///////////////////////////////////////////////////////////////////////
    ///      DO WHAT NEEDS TO BE DONE
    ///////////////////////////////////////////////////////////////////////

  finally
    cds1.Free;
  end;
end;
(それはあまりにも難読化ではない場合)

私は小さなコードで大きな信者だ。

あなたは、あなたは、少なくともあなたはデストラクタ解放を防ぐの一つで例外をさせないことを保証しなければならない(グループは解放が必要とされているかどうかを知ることがnilに初期化して扱う)この(IMO)醜いルートを移動したい場合あなたのオブジェクトの残りの部分。
ような何かます:

function SafeFreeAndNil(AnObject: TObject): Boolean;
begin
  try
    FreeAndNil(AnObject);
    Result :=  True;
  except
    Result := False;
  end;
end;

var cds1  : TClientDataSet;
    cds2  : TClientDataSet;
    IsOK1 : Boolean;
    IsOK2 : Boolean;
begin
  cds1      := Nil;
  cds2      := Nil; 
 try
    cds1      := TClientDataSet.Create(nil);
    cds2      := TClientDataSet.Create(nil);    
    ///////////////////////////////////////////////////////////////////////
    ///      DO WHAT NEEDS TO BE DONE
    ///////////////////////////////////////////////////////////////////////
  finally
    IsOk2 := SafeFreeAndNil(cds2);    // an error in freeing cds2 won't stop execution
    IsOK1 := SafeFreeAndNil(Cds1);
    if not(IsOk1 and IsOk2) then
      raise EWhatever....
  end;
end;

あのビデオ 例外のコンストラクタ&destructors

である例など

var cds1  : TClientDataSet;
    cds2  : TClientDataSet;
begin
  cds1      := Nil;
  cds2      := Nil; 
 try
    cds1      := TClientDataSet.Create(nil);
    cds2      := TClientDataSet.Create(nil);    
    ///////////////////////////////////////////////////////////////////////
    ///      DO WHAT NEEDS TO BE DONE
    ///////////////////////////////////////////////////////////////////////
  finally
    freeandnil(cds2);    //// what has if there in an error in the destructor of cds2
    freeandnil(Cds1);
  end;
end;

何がエラーのデストラクタのcds2

Cds1の破棄は行われません

編集

これからもリソース:

Jim McKeeth優れたビデオ 遅延例外処理 コードの範囲たっての問題に取り扱いの例外は、最後にブロックです。

@mghie:Delphiは、スタック割り当てられたオブジェクトを持ってます:

type
  TMyObject = object
  private
    FSomeField: PInteger;
  public
    constructor Init;
    destructor Done; override;
  end;

constructor TMyObject.Init;
begin
  inherited Init;
  New(FSomeField);
end;

destructor TMyObject.Done;
begin
  Dispose(FSomeField);
  inherited Done;
end;

var
  MyObject: TMyObject;

begin
  MyObject.Init;
  /// ...
end;

残念ながら、上記の例のように示しています。スタック割り当てられたオブジェクトがメモリリークを防ぐことはできません。

だから、これはまだこのようなデストラクタの呼び出しが必要になります:

var
  MyObject: TMyObject;

begin
  MyObject.Init;
  try
    /// ...
  finally
    MyObject.Done;
  end;
end;

OK、私はそれを認める、これは非常に近いオフトピックですが、私は、スタックに割り当てられたオブジェクトは(ない自動デストラクタの呼び出しが存在しない場合、彼らはされていない)ソリューションとして言及されているので、それはこの文脈で面白いかもしれないと思いました。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top