ベストプラクティスをい入れ子にされていない最後に計算書
-
29-08-2019 - |
質問
こんにちはうな入れ子にしてみ&つ諸表ント?
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/以外の/最後にシナリオ。を発見した場合は自分が必要な巣に、私が考えるリファクタリングにもう一つの方法。
編集 清掃、サンフランシスコへのコメント mghie や utku.
編集 変更のオブジェクトを生成しない参考用として必要なことの一例です。
他のヒント
いいものを使っておけば間違いないようになります:
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、私はそれを認める、これは非常に近いオフトピックですが、私は、スタックに割り当てられたオブジェクトは(ない自動デストラクタの呼び出しが存在しない場合、彼らはされていない)ソリューションとして言及されているので、それはこの文脈で面白いかもしれないと思いました。