2008-01-31

Implementing generic IList in Delphi.NET

If at first you don't succeed... hide your astonishment

Last night I had to implement the generic version of IList in delphi. It turned out to be a little more tricky than I had hoped... The compiler didn't always give the most helpful error messages. Anyway, here is a minimal implementation of System.Collections.Generic.IList[T] in Delphi.NET (including a custom enumerator). Just replace all square brackets with the angle brackets (couldn't figure out how to get blogger to show them).

type
TMyListImpl[T] = class(TObject, IList,
ICollection, ICollection[T], IList[T])
function IList.GetEnumerator = IList_GetEnumerator;
function IList.get_Item = IList_get_Item;
public
function IList_GetEnumerator: IEnumerator;
function GetEnumerator: IEnumerator[T];
procedure CopyTo(arr: System.Array; index: integer); overload;
procedure CopyTo(arr: array of T; index: integer); overload;
function get_SyncRoot: System.Object;
function get_IsSynchronized: Boolean;
function get_Count: integer;
procedure Add(value: T); overload;
function Add(value: TObject): integer; overload;
function ICollection_Add(value: TObject): integer;
procedure Clear;
function Contains(value: T): boolean; overload;
function Contains(value: TObject): boolean; overload;
function IndexOf(value: T): integer; overload;
function IndexOf(value: TObject): integer; overload;
procedure Insert(index: integer; value: T); overload;
procedure Insert(index: integer; value: TObject); overload;
function Remove(value: T): Boolean; overload;
procedure Remove(value: TObject); overload;
procedure RemoveAt(index: integer);
function get_IsFixedSize: Boolean;
function get_IsReadOnly: Boolean;
function get_Item(index: integer): T; overload;
procedure set_Item(index: integer; Value: T); overload;
function IList_get_Item(index: integer): TObject; overload;
procedure set_Item(index: integer; Value: TObject); overload;
property Item[index: integer]: T read get_Item write set_Item;
property IsReadOnly: Boolean read get_IsReadOnly;
property IsFixedSize: Boolean read get_IsFixedSize;
property Count: integer read get_Count;
property SyncRoot: System.Object read get_SyncRoot;
property IsSynchronized: Boolean read get_IsSynchronized;
end;

TListEnumerator[T] = class(System.Object,
IEnumerator, IEnumerator[T])
function IEnumerator.get_Current = IEnumerator_get_Current;
strict private
fList: TMyListImpl[T];
FCurrentIndex: integer;
public
constructor Create(list: TMyListImpl[T]);
function get_Current: T;
function IEnumerator_get_Current: TObject;
function MoveNext: Boolean;
procedure Dispose;
procedure Reset;
end;

No comments: