AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Enumerator Problem

Ein Thema von TurboMagic · begonnen am 11. Okt 2025 · letzter Beitrag vom 13. Okt 2025
Antwort Antwort
Seite 1 von 2  1 2      
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.159 Beiträge
 
Delphi 12 Athens
 
#1

Enumerator Problem

  Alt 11. Okt 2025, 21:16
Hallo,

Delphi 12.3 und gegeben sei diese Klassendeklaration:

Delphi-Quellcode:
  TProductTreeItemList = class(TObjectList<TProductTreeItem>,
                               IEnumerator<TProductTreeItem>)
Ich will also das IEnumerator Interface umsetzen.
AddRef usw. hab' ich schon drin.

Nur: wie muss GetCurrent deklariert werden, damit mich
der Compiler auch mag?

das ist es nicht:
function GetCurrent: TProductTreeItem; Der Compiler meckert so:

[dcc32 Fehler] ProductTreeItemList.pas(49): E2211 Deklaration von 'GetCurrent' unterscheidet sich von der Deklaration in Interface 'System.IEnumerator<ProductTreeItem.TProductTreeIt em>'
System.pas(1011): Verwandtes Member: function GetCurrent: TObject;

Ja, ich hatte auch schon mal ein zusätzliches GetCurrent: TObject; overload; Hat aber auch nix gebracht.
Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.877 Beiträge
 
Delphi 12 Athens
 
#2

AW: Enumerator Problem

  Alt 11. Okt 2025, 22:36
Zitat:
Delphi-Quellcode:
  IEnumerator<T> = interface(IEnumerator)
    function GetCurrent: T;
Das TProductTreeItem im Interface ist aber auch das selbe, wie in der Implementation?



Brauchst du unbedingt das IEnumerator<> oder reicht "ein" Enumerator für FOR-Schleifen?
Bei Letzterem muß die Methide einfach nur so lauten function GetEnumerator: ....; inline; und irgendeine Klasse zurück geben,
mit Methoden die so heißen (mit oder ohne inline)
Delphi-Quellcode:
function GetCurrent: ...; inline;
function MoveNext: Boolean; inline;
property Current: Pointer read ...;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
10.203 Beiträge
 
Delphi 13 Florence
 
#3

AW: Enumerator Problem

  Alt 11. Okt 2025, 22:51
Leider ist das mit IEnumerator echt nicht so schön, da du GetCurrent mit unterschiedlichen Rückgabewerten brauchst. Overload geht nicht, da beide keine Parameter haben. Du musst daher eine der Methoden anders nennen und umleiten. Das funktioniert so:
Delphi-Quellcode:
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    function GetCurrent: TObject;
    function MoveNext: Boolean;
    procedure Reset;
    function IEnumerator<TProductTreeItem>.GetCurrent = GetCurrentT;
    function GetCurrentT: TProductTreeItem;
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.159 Beiträge
 
Delphi 12 Athens
 
#4

AW: Enumerator Problem

  Alt 12. Okt 2025, 10:48
Hallo,

ja damit komme ich einen Schritt weiter:

Leider ist das mit IEnumerator echt nicht so schön, da du GetCurrent mit unterschiedlichen Rückgabewerten brauchst. Overload geht nicht, da beide keine Parameter haben. Du musst daher eine der Methoden anders nennen und umleiten. Das funktioniert so:
Delphi-Quellcode:
    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
    function GetCurrent: TObject;
    function MoveNext: Boolean;
    procedure Reset;
    function IEnumerator<TProductTreeItem>.GetCurrent = GetCurrentT;
    function GetCurrentT: TProductTreeItem;
Aber: wenn ich jetzt irgendwo sowas tun will:

Delphi-Quellcode:
TMyClass.DoSomething(ProductData : IEnumerator<TProductTreeItem>;);
begin
  for var TreeItem in ProductData do
    ;
end;
Dann meckert der Compiler:
[dcc32 Fehler] ProductManagerTreeDisplay.pas(139): E2431 for-in-Anweisung arbeitet nicht mit Kollektionstyp 'System.IEnumerator<ProductTreeItem.TProductTreeIt em>', weil 'System.IEnumerator<ProductTreeItem.TProductTreeIt em>' kein Element für 'GetEnumerator' enthält oder darauf nicht zugegriffen werden kann

Nur hab' ich noch nicht kapiert wie ich GetEnumerator umsetzen muss. Alle Versuche bisher scheiterten.
z. B. sowas hier:

Delphi-Quellcode:
function GetEnumerator: IEnumerator<TProductTreeItem>;
function IEnumerator<TProductTreeItem>.GetEnumerator = GetEnumeratorT;
function GetEnumeratorT: IEnumerator<TProductTreeItem>;
Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
10.203 Beiträge
 
Delphi 13 Florence
 
#5

AW: Enumerator Problem

  Alt 12. Okt 2025, 12:03
Wenn du for..in verwenden möchtest, muss deine Liste die Methode GetEnumerator implementieren und dort den Enumerator zurückliefern und nicht selbst implementieren. Du musst also IEnumerable<TProductTreeItem> implementieren. Und du benötigst eine Enumerator-Klasse, die IEnumerator<TProductTreeItem> implementiert.

Warum nicht direkt in der Klasse implementieren? Es könnten ja mehrere verschachtelte Enumerationen laufen. Die brauchen daher eigene Instanzen des Enumerators.
Sebastian Jänicke
AppCentral

Geändert von jaenicke (12. Okt 2025 um 12:06 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.159 Beiträge
 
Delphi 12 Athens
 
#6

AW: Enumerator Problem

  Alt 12. Okt 2025, 17:21
Hallo,

ich verstehe grob was du meinst, bekomme es aber nicht hin.

Hier mal was ich so habe:

Delphi-Quellcode:
  TProductTreeItemList = class;

  TProductTreeItemListEnumerator = class(TObject)
  strict private
    FIndex : Integer;
    FList : TProductTreeItemList;
  public
    constructor Create(AList: TProductTreeItemList);
    function GetCurrent: TObject; inline;
    function GetCurrentT: TProductTreeItem;
    function MoveNext: Boolean; inline;
    property Current: TProductTreeItem
      read GetCurrentT;
  end;

  TProductTreeItemList = class(TObjectList<TProductTreeItem>)
  strict private
    [..]
    function GetEnumerator: TProductTreeItemListEnumerator;
  public
    [..]

    function GetLastGroupProductIndex(GroupID: Integer): TGroupProductIndexRec;
  end;



function TProductTreeItemList.GetEnumerator: TProductTreeItemListEnumerator;
begin
  Result := TProductTreeItemListEnumerator.Create(self);
end;

function TProductTreeItemList.GetLastGroupProductIndex(GroupID: Integer): TGroupProductIndexRec;
var
  NewGroupFound : Boolean;
begin
  NewGroupFound := false;
  Result.GroupIndex := 0;
  Result.NextProductIndex := 0;

// Hier meckert der COmpiler:
// [dcc32 Fehler] ProductManagerTreeDisplay.pas(139): E2431 for-in-Anweisung arbeitet nicht mit Kollektionstyp
// 'System.IEnumerator<ProductTreeItem.TProductTreeItem>', weil 'System.IEnumerator<ProductTreeItem.TProductTreeItem>'
// kein Element für 'GetEnumerator' enthält oder darauf nicht zugegriffen werden kann
  for var GItem in self do
  begin
    if (GItem.NodeType = ntGroup) then
    begin
    end;
  end;
end;
Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.877 Beiträge
 
Delphi 12 Athens
 
#7

AW: Enumerator Problem

  Alt 12. Okt 2025, 17:28
Zitat:
oder darauf nicht zugegriffen werden kann
strict private?
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.159 Beiträge
 
Delphi 12 Athens
 
#8

AW: Enumerator Problem

  Alt 12. Okt 2025, 17:40
Zitat:
oder darauf nicht zugegriffen werden kann
strict private?
Fast: strict protected.
Ok, ich hab' das jetzt public gemacht und nun geht es zumindest an der Stelle.
Jetzt knallt es wo ganz anders wo ich das ding mal irgendwo verwende.

Da suche ich nacher danach. Dort muss ich wohl was anderes als bisher übergeben.
Aber nach meinem Verständnis erzeugt die For Schleife ja eigentlich intern diesen Enumerator, oder?

Nur aus meinem Code sehen ich noch keinen Zusammenhang von der Liste zum Enumerator.
Andersherum natürlich schon.

Wenn ich also irgendwo die Liste übergeben will udn dann mittels for Schleife drüber gehen will
kann der Compiler ja wohl nicht wissen, dass ich da einen Enumerator habe.
Da müsste meine Liste in class(...) ja wohl noch das IEnumerable<TProductTreeItem> drin?
Aber wenn ich das reinnehme, sagt er, dass mein GetEnumerator sich unterscheiden würde.
Naja, der liefert ja auch ein TProductTreeItemListEnumerator und füge ich nur IEnumerable ohne <>
hinzu, meckert er dass meine GetEnumerator Signatur sich von der aus IEnumerable unterscheidet.

Gibt's mal irgendwo ein einfaches aber komplettes Beispiel inkl. Generics?
Hab' schon mal versucht aus TList schlau zu werden (ohne Generics), da ist aber nirgends irgendwas
bezüglich Interfaces notiert.
Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
10.203 Beiträge
 
Delphi 13 Florence
 
#9

AW: Enumerator Problem

  Alt 12. Okt 2025, 18:48
Hier ein Beispiel... Nicht schön (Interface-Referenzzählung deaktiviert und Mischung von Interface- und Objektreferenzen), aber kurz. Ich gehe bei dir einfach mal davon aus, dass du es dann selbst sauber machst:
Delphi-Quellcode:
type
  TProductTreeItem = class
  private
    FName: string;
  public
    constructor Create(const AName: string);
    property Name: string read FName;
  end;

  TProductTreeItemList = class;

  TProductTreeItemEnumerator = class(TInterfacedObject, IEnumerator<TProductTreeItem>, IEnumerator)
  strict private
    FIndex: Integer;
    FList: TProductTreeItemList;
  protected
    function GetCurrentTyped: TProductTreeItem;
    function IEnumerator<TProductTreeItem>.GetCurrent = GetCurrentTyped;
    function GetCurrent: TObject;
  public
    constructor Create(AList: TProductTreeItemList);
    function MoveNext: Boolean;
    procedure Reset;
  end;

  TProductTreeItemList = class(TObjectList<TProductTreeItem>, IEnumerable<TProductTreeItem>)
  public
    function GetEnumerator: IEnumerator;
    function GetEnumeratorTyped: IEnumerator<TProductTreeItem>;
    function IEnumerable<TProductTreeItem>.GetEnumerator = GetEnumeratorTyped;

    function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  end;

constructor TProductTreeItem.Create(const AName: string);
begin
  inherited Create;
  FName := AName;
end;

constructor TProductTreeItemEnumerator.Create(AList: TProductTreeItemList);
begin
  inherited Create;
  FList := AList;
  FIndex := -1;
end;

function TProductTreeItemEnumerator.GetCurrentTyped: TProductTreeItem;
begin
  if (FIndex < 0) or (FIndex >= FList.Count) then
    raise Exception.Create('Enumerator: Current out of range');
  Result := FList[FIndex];
end;

function TProductTreeItemEnumerator.GetCurrent: TObject;
begin
  Result := GetCurrentTyped;
end;

function TProductTreeItemEnumerator.MoveNext: Boolean;
begin
  Inc(FIndex);
  Result := FIndex < FList.Count;
end;

procedure TProductTreeItemEnumerator.Reset;
begin
  FIndex := -1;
end;

function TProductTreeItemList.GetEnumerator: IEnumerator;
begin
  Result := TProductTreeItemEnumerator.Create(Self);
end;

function TProductTreeItemList.GetEnumeratorTyped: IEnumerator<TProductTreeItem>;
begin
  Result := TProductTreeItemEnumerator.Create(Self);
end;

function TProductTreeItemList.QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
begin
  if GetInterface(IID, Obj) then
    Result := S_OK
  else
    Result := E_NOINTERFACE;
end;

function TProductTreeItemList._AddRef: Integer; stdcall;
begin
  Result := -1;
end;

function TProductTreeItemList._Release: Integer; stdcall;
begin
  Result := -1;
end;

procedure Demo;
var
  List: TProductTreeItemList;
  Enum: IEnumerable<TProductTreeItem>;
  Item: TProductTreeItem;
begin
  List := TProductTreeItemList.Create(True);
  try
    List.Add(TProductTreeItem.Create('Apfel'));
    List.Add(TProductTreeItem.Create('Birne'));
    List.Add(TProductTreeItem.Create('Orange'));

    Enum := List;
    for Item in Enum do
      ShowMessage(Item.Name);
    Enum := nil;
  finally
    List.Free;
  end;
end;
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.159 Beiträge
 
Delphi 12 Athens
 
#10

AW: Enumerator Problem

  Alt 12. Okt 2025, 20:19
Hallo,

danke für dein ausführliches Beispiel.
Nur mag es der Compiler an einer anderen Stelle noch nicht ganz.
DIe Liste hat auch diese Methode und der Compiler beharrt drauf, dass GItem ein TObject
sein muss und nicht ein TProductTreeItem. Warum? Auch der Versuch for var GItem: TProductTreeItem
führt nicht weiter, da sagt er dann, das sei nicht kompatibel. Irgendwie scheint er die typisierten
GetEnumerator Methode nicht zu kennen/mögen. Hab' das aber genauso wie bei dir umgesetzt.

Delphi-Quellcode:
function TProductTreeItemList.GetLastGroupProductIndex(GroupID: Integer): TGroupProductIndexRec;
begin
  for var GItem in self do
  begin
    if (GItem.NodeType = ntGroup) then
    begin
    end;
  end;
end;
Grüße
TurboMagic
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz