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プロパティとして外部に出してやるという手抜き実装
type
    IListGen<T> = interface
        function _GetList: TList<T>;
        property Item: TList<T> read _GetList;
    end;

    TListGen<T> = class(TInterfacedObject, IListGen<T>)
    private
        FList: TList<T>;
        function _GetList: TList<T>;
    public
        constructor Create;
        destructor Destroy; override;
        property Item: TList<T> read _GetList; // ココ
    end;

implementation

{ TListGen<T> }

constructor TListGen<T>.Create;
begin
    FList := TList<T>.Create;
end;

destructor TListGen<T>.Destroy;
begin
    FList.Free;
    inherited;
end;

function TListGen<T>._GetList: TList<T>;
begin
    Exit(FList);
end;
こんな感じで Item という記述は増えますが、Generic で interface なリストが使えます
var List: IListGen<string>;
begin
    List := TListGen<string>.Create;
    List.Item.Add('foo');
    List.Item.Items[0] // 'foo'
end;

コメント