StringListがCreateされているかどうかの判定

解決


Jun2013  2013-06-27 19:57:42  No: 44767  IP: 192.*.*.*

TStringListを多用しています。
Createされていない判定でもってCreateするとか、
Createされている判定でもって次の処理をするとかしたいと考えています。
エラートラップ以外でCreateの済・未済を判定する方法はあるのでしょうか?

編集 削除
Nov  2013-06-27 20:40:57  No: 44768  IP: 192.*.*.*

Assigned()のことでしょうか?

編集 削除
mona  2013-06-27 22:36:47  No: 44769  IP: 192.*.*.*

procedure TForm1.Button1Click(Sender: TObject);
var
  aSL:TStringList;
begin
  aSL := TStringList.Create;
  aSL.Free;
  if Assigned(aSL) then
    beep;
end;

Assigned()だけでは判定できない場合がありますので
解放後のnilの代入、FreeAndNil()もお忘れなく。

編集 削除
Jun2013  2013-07-01 09:29:28  No: 44770  IP: 192.*.*.*

早速の返答ありがとうございます。
Assignedを試しましたがうまくいきません。Assignedは『割り当てられた』と
いうことと理解しており、以下のケースだとstep2のみメッセージ表示
されると期待しますが、すべて表示されます。
Assignedの利用方法が誤っているのでしょうか?

procedure TForm1.Button1Click(Sender: TObject);
var
  aSL:TStringList;
begin
  if Assigned(aSL) then 
    ShowMessage('step1 before create');

  aSL := TStringList.Create;
  if Assigned(aSL) then
    ShowMessage('step2 after create');

  aSL.Free;
  if Assigned(aSL) then
    ShowMessage('step3 after free');

end;

編集 削除
Nov  2013-07-01 21:01:50  No: 44771  IP: 192.*.*.*

ローカル変数(aSL)では駄目です。
TForm1のメンバか、グローバルにしてください。

monaさんの例は、関数内で完結(順番が重要)しているからOKなのです。

編集 削除
 2013-07-01 21:23:54  No: 44772  IP: 192.*.*.*

単にnilを代入しているかどうかだけの違いではないでしょうか。
次のように aSL := nil を入れてやると、質問者の意図した動きになります。

procedure TForm1.Button1Click(Sender: TObject);
var
  aSL:TStringList;
begin
  aSL := nil; // 追加。
  if Assigned(aSL) then
    ShowMessage('step1 before create');

  aSL := TStringList.Create;
  if Assigned(aSL) then
    ShowMessage('step2 after create');

  aSL.Free;
  aSL := nil;  // 追加。
  if Assigned(aSL) then
    ShowMessage('step3 after free');
end;

編集 削除
Nov  2013-07-01 21:28:34  No: 44773  IP: 192.*.*.*

>monaさんの例は、関数内で完結(順番が重要)しているからOKなのです。

OKといっても、FreeAndNil()を忘れた場合の例をしめすためのものなので、
そこのところは、誤解しないでください。
ちなみに、3番目のメッセージが表示されないなのは、monaさんの忠告を
忘れた結果だということは、分かりますよね。...念のため。

編集 削除
Harry  2013-07-01 23:55:55  No: 44774  IP: 192.*.*.*

たぶん分かってないと思いますので…monaさんの言葉をよく読んでください。
>Assigned()だけでは判定できない場合がありますので
> 解放後のnilの代入、FreeAndNil()もお忘れなく。

つまり変数を使い回す際は、あ さんの例のように、
  aSL.Free;
  aSL := nil;  // 追加。
とするか、
  FreeAndNil(aSL);
としてnilを代入しないと、後のAssigned()で判定できません。FreeだけではaSLにnilは代入されませんので。

初心者の方はこの辺りで悩むと思いますので、ぶっちゃけていくつかタネ明かしをしますと、
・ TStringList型の変数 aSL とは、用途がTStringList型に限定されているポインタ型の変数です。
・ ポインタ型変数の正体はInteger型です。が、コンパイラはこれに特別な意味を与え、特有の働きをさせます。
・ nilの正体は、単なる 0(ゼロ)です。
・ 「この場合の」Assigned()は、 aSLの値がnil(つまり 0)でなければTrueを返すという関数です。
「この場合の」と但し書きを付けたのは、手続き型変数(例えばOnなんとかというイベントのプロパティ)
では違うからです。詳しくはヘルプでAssignedと手続き型を調べてください。

もう一つ、Jun2013さんが誤解している点があります。
var
  aSL: TStringList;
このようにローカル変数を宣言しただけでは、aSLは(nilに)初期化されません。
というかローカル変数は基本的に初期化されないのが原則で、最初に入っている値は不定だと思ってください。
これはDelphiがネイティブコンパイラであるゆえに、無駄な処理を省き、ユーザーのコードですべてを
まかなってもらおうという姿勢だと思います。
※ただしString型や、クラス型・レコード型のインスタンス内の変数、グローバル変数などは初期化されます。

Delphi言語ガイド - データ型、変数、定数 - 変数 - Delphi リファレンス
http://docwiki.embarcadero.com/RADStudio/XE4/ja/%E5%A4%89%E6%95%B0
>明示的に初期化されていないグローバル変数はコンパイラによって 0 に初期化されます。
>オブジェクトインスタンスデータ(フィールド)も 0 に初期化されます。
>Win32 プラットフォームでは、ローカル変数の内容は、値が代入されるまで定義されません。

編集 削除
Jun2013  2013-07-02 09:28:24  No: 44775  IP: 192.*.*.*

Delphiの仕様とその利用方法が理解できました。
回答していただいたみなさまに感謝しています。

ありがとうございました。

編集 削除