2012年11月19日月曜日

ジェネリクス

Delphi の 2009 から?ジェネリクスに対応しました。
純粋に、そういえば、どういう構造で管理してるのかな?と思ってソースを見てみました。
そうすると、下のようになっており

TList<T> = class(TEnumerable<T>)
private
type
arrayofT = array of T;

動的配列を使っていました。
なるほど!これならオブジェクトの解放を自分で管理しなくて済みますね!
Delphi の動的配列は解放をコンパイラに任せられるためです。
あって良かった動的配列!

とはいえ、当然のことですが、インスタンスの場合は解放が必要になります。
例えば、以下のコードの様にインスタンスを生成した場合、破棄が必要です。

program Project1;
 
{$APPTYPE CONSOLE}
 
uses
System.Generics.Collections;
 
type
// TList で管理されるクラス
TTest = class
public
constructor Create(const iIndex: Integer); reintroduce;
end;
 
// TTest クラスを型データとする
TObjectList = TList<TTest>;
 
{ TTest }
 
constructor TTest.Create(const iIndex: Integer);
begin
Writeln('TTest.Created !, Index = ', iIndex);
end;
 
procedure Test;
var
List: TObjectList;
i: Integer;
begin
List := TObjectList.Create;
try
// インスタンスの生成
for i := 0 to 9 do
List.Add(TTest.Create(i));
 
// インスタンスの解放
for i := 0 to List.Count - 1 do
List[i].Free;
finally
List.Free;
end;
end;
 
begin
Test;
Readln;
end.

そう考えると TList 等のジェネリクス型と相性が良いのは record の様な気がします。
解放を考えなくて済みますから。

ただ、ここで注意したいのは以前書いた記事のように、record はあくまでも record であるという事です。
TList と組み合わせて使うと、この罠に引っかかりやすいので注意が必要です。

2 件のコメント:

  1. 私もrecordの罠にはまったことがあります。結局面倒でもClassとTObjectListを使いました。
    Genericsはまだ使う機会がなかったのですが、同様にTList<T>でなくTObjectList<T>を使うのが便利かもしれません。

    返信削除
  2. この罠には引っかかりやすいですよね。
    確かに TObjectList を使えば解放を任せられるので良いと思います。

    返信削除