About the author
Working on some coding last night, and would like to point out and remind myself how to implement IEnumerable<T> properly.
When implementing IEnumerable<T>, there is always a need to use the method resolution clause in order to avoid conflict of the similar names in IEnumerable and IEnumerable<T>, since both declares the GetEnumerator method with the same type signature.
WORKING EXAMPLE: IEnumerable<T>
type TTestEnumerable<T> = class(TInterfacedObject, IEnumerable<T>) function GenericGetEnumerator: IEnumerator<T>; function GetEnumerator: IEnumerator; function IEnumerable<T>.GetEnumerator = GenericGetEnumerator; end;
Similarly, for IEnumerator<T>:
type TTestEnumerator<T> = class(TInterfacedObject, IEnumerator<T>) function GetCurrent: TObject; function MoveNext: Boolean; procedure Reset; function GenericGetCurrent: T; function IEnumerator<T>.GetCurrent = GenericGetCurrent; end;
The lessons learnt from the above is that whenever interfaces with generic ancestors are involved with similarly named methods, one needs to declare the ancestor interface method, and use method resolution clause to redirect the descendent methods.
While working on the above, I filed QC 116432, on how class completion doesn't work when generics are involved.
Continued discussion of undocumented Delphi 8 Property Access Specifiers, and other ways of adding and removing delegates / events handlers, including clearing the list of all the delegates / event handlers.
This article discusses the new Delphi 8 property access specifiers.
A method pointer is now the same as a global procedure, ie, procedure of object = procedure.