Delphi で Generics で Interface なリスト IList

Delphi の Generics なリストを interface で作成したい

検索結果のリストを渡すとき等、リストそのものがインターフェイスじゃないので、受け取り側で TList<IHoge> の中身だけ、別のリストへコピーとかになってしまうわけです

そこで IList<IHoge> みたいなのがあれば、リストそのものを代入すれば参照カウンタが上がって安全にかつ迅速に引き渡せるハズ

調べたら 型が IInterface に制約される System.Classes.IInterfaceList とかいうのがあるので、THoge(List.Items[I]) のように取り出し時にキャストしてやれば使えます
※リストは参照なので、受け取り側で変更すると受け渡し側へも影響ありです
IInterfaceList で OKな方はここまでで完了

Delphi で interface のベースクラスは 「TInterfacedObject を継承してないと参照カウンタは実装されません」とかいう制約がある
TList との 多重継承はNGなので、TInterfacedObjectを継承したクラスの中で TList 型の変数を持って、出入り口を作り直せとかいう事らしい(ChatGPTの回答もそれだった)
先程の IInterfaceList も private に FList: TThreadList<IInterface> とかいうリストを持ってました
それって Count やら Items やら(無駄に)再定義して、使っていくうちにアレが足りないとかなりそうじゃないですか...

ということで、TList をそのまま Itemプロパティとして外部に出してやるという手抜き実装
  1. type  
  2.     IListGen<T> = interface  
  3.         function _GetList: TList<T>;  
  4.         property Item: TList<T> read _GetList;  
  5.     end;  
  6.   
  7.     TListGen<T> = class(TInterfacedObject, IListGen<T>)  
  8.     private  
  9.         FList: TList<T>;  
  10.         function _GetList: TList<T>;  
  11.     public  
  12.         constructor Create;  
  13.         destructor Destroy; override;  
  14.         property Item: TList<T> read _GetList; // ココ  
  15.     end;  
  16.   
  17. implementation  
  18.   
  19. { TListGen<T> }  
  20.   
  21. constructor TListGen<T>.Create;  
  22. begin  
  23.     FList := TList<T>.Create;  
  24. end;  
  25.   
  26. destructor TListGen<T>.Destroy;  
  27. begin  
  28.     FList.Free;  
  29.     inherited;  
  30. end;  
  31.   
  32. function TListGen<T>._GetList: TList<T>;  
  33. begin  
  34.     Exit(FList);  
  35. end;  
こんな感じで Item という記述は増えますが、Generic で interface なリストが使えます
  1. var List: IListGen<string>;  
  2. begin  
  3.     List := TListGen<string>.Create;  
  4.     List.Item.Add('foo');  
  5.     List.Item.Items[0// 'foo'  
  6. end;  

コメント