Wieso benutzt man IEnumerator?

2 Antworten

Was ist ' yield return'

Kontextabhängiges yield-Schlüsselwort: C#-Referenz | Microsoft Docs

IEnumerable bedeutet, das Objekt kann IEnumerator zurück liefern. Das IEnumerator ist eine Art Iterator-Pattern. Man bekommt nicht eine Liste von Objekte zurück, sondern ein Objekt, was das jeweils nächste Objekt holen kann.

Für z.B. Datenbank-Operationen ist das besonders praktisch. Man führt die DB-Abfrage aus und bekommt z.B. 10 Datensätze zurück, die liegen dann im RAM. Das Enumerator-Objekt holt jedes mal das nächste Element (erst das Erste, dann das Zweite, und so weiter), was aber für die ersten 10 Datensätze eigentlich nur bedeutet, einen Index weiter zu zählen. Bis man dann den 11. Datensatz haben will, denn dann wird nicht nur ein Index hochgezählt, sondern es werden die nächsten 10 Datensätze von der Datenbank abgerufen - und die Datenbank hatte bis dahin auch Zeit, die nächsten 10 Datensätze zu suchen.
Etwas ähnliches mache ich gerade mit einem USB-Gerät, das schickt in Abständen Daten und meine Implementierung liefert ein Enumerable, was mit jedem MoveNext() den jeweils nächsten Datensatz holt oder wartet, bis er da ist.

Tatsächlich ist es das, was die foreach-Schleife macht, sie nutzt IEnumerable um ein IEnumerator-Objekt abzurufen und nach jedem Durchlauf wird MoveNext() aufgerufen, um das jeweils nächste Objekt zu liefern.

So ein Enumerator kann aber ziemlich nervig zu entwickeln sein, das yield return macht es um einiges einfacher, weil der Compiler dann eine StateMachine drum herum generieren kann, die alles nötige implementiert.
Schau dir die Doku an und debugge einfach mal durch, dann siehst Du, wie es sich verhält.

wieso der Code so sein muss wie er ist

Muss er nicht.

Ich habe keine Ahnung von Unity, aber bei normalen Business-Programmen verwendet man normalerweise den generischen IEnumerator. Außerdem nutzt man es, um als Item ein tatsächliches Ergebnis zurück zu liefern und nicht, um zu warten. In normalen Business-Programmen nutzt man für sowas das Task asynchronous programming model oder andere Konzepte.

Oder es ist ein Unity-spezifisches Konzept, aber dann musst Du die Unity-Doku lesen und der Enumerator ist dann nur ein Werkzeug für ein ganz anderes Konzept.

Woher ich das weiß:Berufserfahrung – C#.NET Senior Softwareentwickler

1TheCrazy 
Fragesteller
 26.11.2021, 18:50

Danke, hab zwar nur die Hälfte verstanden (und probier nicht es mir zu erklären, das kommt mit der Zeit) und brauche es schlussendlich auch nicht mehr, aber sehr vielen Dank.

0
1TheCrazy 
Fragesteller
 26.11.2021, 18:58
@1TheCrazy

Aber keine Sorge ich bin nicht dumm nur jung🙂

0
Palladin007  27.11.2021, 12:52
@1TheCrazy
brauche es schlussendlich auch nicht mehr

Das ist ein Irrglaube.

Das ganze Thema ist ein sehr tief in .NET vorhandenes Konzept, quasi überall wird es genutzt und sobald Du die foreach-Schleife nutzt, nutzt Du es auch.

Wenn Du z.B. mit Datenbanken (mit einem ORM, die bieten meist einen LINQ-Provider) arbeitest, dann ist dieses Thema DAS große Konzept, die ganze Technologie baut darauf auf. Man kann so eine LINQ-Abfrage zwar normal in einer foreach-Schleife nutzen, aber gleichzeitig kann man sich auch große Performance-Probleme (und andere Probleme) einbauen, die dann erst irgendwann später auffallen, nur nicht da, wo der eigentliche Code steht.
Alle dieser Fälle, die ich bisher gesehen habe, waren auf mangelndes Verständnis zurückzuführen.

Aber ich gebe zu: Ohne OOP und was eine Abstraktion ist, wirklich verinnerlicht zu haben, ist es schwer, so ein Konzept zu verstehen.

0
1TheCrazy 
Fragesteller
 27.11.2021, 17:43
@Palladin007

War auch nur so gemeint in diesem Stück Code, aber brauche es doch. Hattest also Recht.

0

Es handelt sich dabei um eine Schleife mit verzögerter Ausführung.

Wenn du FadeOut aufrust um das IEnumerator Objekt zu erhalten wird die Schleife nicht sofort ausgeführt sondern erst dann wenn man lesend auf das IEnumerator Objekt zugreift.

Das hat den Vorteil, dass bestimmte Methoden einfach Effizienter gestaltet werden können.

Wenn du zB das IEnumerator Objekt in einer foreach Schleife verwendest macht das der Kompiler im wesentlich nur zu einer einzigen Schleife nämlich der for Schleife di in dieser Funktion steht.

Würdest du hingegen ein Array oder eine Liste zurückgeben würde zuerst diese for Schleife durchlaufen und erst danach nochmal die foreach Schleife wobei du in diesem Fall eine Schleifenausführung mehr hast.

Wenn du yield return verwendest musst du zudem immer ein IEnumerator zurückgeben. Das yield return bedeutet nämlich nur wenn das IEnumerator nach einem Wert gefragt wird gib diesen Wert zurück. Das normale Return bedeutet hingegen dass der Wert sofort zurückgegeben wird.


1TheCrazy 
Fragesteller
 25.11.2021, 20:18

Danke, habe zwar beim ersten Durchlesen nur die Hälfte verstanden, aber ich denke das wird morgen <3

0
1TheCrazy 
Fragesteller
 27.11.2021, 12:40
@PeterKremsner

Also ich hab jetzt ein Problem und zwar wird die IEnumarator Methode aufgerufen ohne dass sie das soll. Bei einer Normalen Methode ist dies nicht der Fall, doch wenn ich die benutze verhlt sich eine while-Schleife anders. Kann ich es verhindern dass diese aufgerufen wird? Wie?

0
PeterKremsner  27.11.2021, 15:44
@1TheCrazy

Was bedeutet sie wird aufgerufen ohne dass sie das soll?

Wann und wo wird diese Aufgerufen und wie stellst du fest, dass diese Aufgerufen wird.

Die Methode selbst die das IEnumerable liefert sollt nur beim Call aufgrufen werden. Der Iterationsblock selbst also das mit dem yield return wird natürlich bei jedem Aufruf einer Methode des Iterators aufgerufen, das ist normal und auch so gewollt.

0
1TheCrazy 
Fragesteller
 28.11.2021, 11:46
@1TheCrazy

Wie kann man eine While-Schleife in einer Coroutine verzögern, ohne dass sie die "Rechnungen in ihr schon ausführt?

Ich habe eine While-Schleife in einer Coroutine und wenn ich diese mit

'yield return new WaitForSeconds(delay)'

verzögere, passiert das was über eine oder mehrere Sekunden verteilt sein sollte, in einem Frame. Wie kann ich das verhinder?

0
PeterKremsner  28.11.2021, 12:02
@1TheCrazy

Also ich kenne die WaitForSeconds Methode nicht aber was liefert die zurück?

Ein yield return bei einem Wait macht imho keinen wirklichen Sinn, weil das WaitForSeconds ja nicht sofort ausgeführt wird sondern weil es erst dann instanziert wird wenn über den Iterator iterriert wird.

0