Richtige Verwendung von "Rendite"
Den Rendite Schlüsselwort ist einer von denen, keywords in C#, weiter zu mystifizieren, mich, und noch nie war ich zuversichtlich, dass ich Sie mit es richtig.
Der folgenden zwei Stücke von code, die, wird Sie bevorzugt und warum?
Version 1: Mit yield return
public static IEnumerable<Product> GetAllProducts()
{
using (AdventureWorksEntities db = new AdventureWorksEntities())
{
var products = from product in db.Product
select product;
foreach (Product product in products)
{
yield return product;
}
}
}
Version 2: Zurückgeben der Liste
public static IEnumerable<Product> GetAllProducts()
{
using (AdventureWorksEntities db = new AdventureWorksEntities())
{
var products = from product in db.Product
select product;
return products.ToList<Product>();
}
}
Kommentar zu dem Problem - Öffnen
Ertrag
ist an " IEnumerable<T>
und seine Art. Es ist in irgendwie lazy evaluation hier ist eine große Antwort auf die ähnliche Frage. stackoverflow.com/questions/15381708/...
Hier ist ein gutes Beispiel: stackoverflow.com/questions/3392612/...
Ich sehe ein gutes Beispiel für die Verwendung von
Rendite
, wenn der code iteriert durch die Ergebnisse von GetAllProducts()
ermöglicht es dem Benutzer eine chance vorzeitig Abbrechen der Verarbeitung. Ich fand diesen thread sehr hilfreich: programmers.stackexchange.com/a/97350/148944
InformationsquelleAutor der Frage senfo | 2009-01-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Neige ich zum Rendite-Rendite, wenn ich die Berechnung des nächsten Elements in der Liste (oder auch die nächste Gruppe von Elementen).
Mit Ihrer Version 2, müssen Sie die gesamte Liste vor der Rückkehr.
Durch die Verwendung von yield Rendite, die Sie wirklich nur brauchen, um über den nächsten Punkt vor der Rückkehr.
Unter anderem, dies erleichtert die Verteilung der Rechenaufwand für komplexe Berechnungen über einen größeren Zeit-Rahmen. Zum Beispiel, wenn die Liste angeschlossen wird, bis zu einer GUI und die Benutzer nie auf die Letzte Seite, die Sie nie berechnen die endgültigen Elemente in der Liste.
Einem anderen Fall, wo Rendite-Rendite vorzuziehen ist, wenn die IEnumerable-Schnittstelle stellt eine unendliche Menge. Betrachten Sie die Liste der Primzahlen, oder eine unendliche Liste von Zufallszahlen. Können Sie nie wieder den vollen IEnumerable auf einmal, so dass Sie verwenden yield-return-die Rückkehr der Liste inkrementell.
In Ihrem Beispiel, Sie haben die vollständige Liste der Produkte, also würde ich die Version 2.
InformationsquelleAutor der Antwort abelenky
Auffüllen einer temporären Liste, ist wie das herunterladen der gesamten video -, in der Erwägung, dass mit
yield
ist wie streaming, video.InformationsquelleAutor der Antwort anar khalilov
Als ein konzeptionelles Beispiel für das Verständnis, wenn Sie nutzen sollten
yield
, sagen wir, die MethodeConsumeLoop()
Prozesse die Elemente zurückgegeben werden/erbracht durchProduceList()
:Ohne
yield
der AufrufProduceList()
eine lange Zeit dauern, weil Sie haben, um vervollständigen die Liste vor der Rückkehr:Mit
yield
es wird angeordnet, Art der Arbeit "parallel":Und schließlich, wie viele vor haben schon vorgeschlagen, Sie sollten Version 2, da Sie bereits die fertige Liste sowieso.
InformationsquelleAutor der Antwort Kache
Dies scheint ein bizarrer Vorschlag, aber ich habe gelernt, wie man die
yield
- Schlüsselwort in C# durch das Lesen ein Referat über Generatoren in Python: David M. Beazley ist http://www.dabeaz.com/generators/Generators.pdf. Sie brauchen nicht zu wissen, viel Python zu verstehen, die Präsentation habe ich das nicht. Ich fand es sehr hilfreich bei der Erklärung nicht nur, wie Generatoren arbeiten, aber warum sollten Sie Pflege.InformationsquelleAutor der Antwort Robert Rossney
Ich weiß, das ist eine alte Frage, aber ich würde gerne ein Beispiel dafür, wie das yield-Schlüsselwort kann kreativ genutzt. Ich habe wirklich profitiert von dieser Technik. Ich hoffe, dies hilft jemand, der stößt auf diese Frage.
Hinweis: denken nicht über das yield-Schlüsselwort bloß als eine weitere Methode für den Aufbau einer Sammlung. Ein großer Teil der macht der Ertrag kommt in der Tatsache, dass die Ausführung ist angehalten in Ihrem
Methode oder Eigenschaft, bis der aufrufende code iteriert über den nächsten Wert. Hier mein Beispiel:
Mit dem yield-Schlüsselwort (neben Rob Eisenburg ist Caliburn.Micro Coroutinen Umsetzung) ermöglicht mir, mich auszudrücken, einen asynchronen Aufruf einer web-service wie diesem:
Was wird dies tun, ist meine BusyIndicator, rufen Sie die Login-Methode auf meiner web-service, meine IsLoggedIn flag auf den Wert zurück, und dann drehen Sie das BusyIndicator-zurück off.
Hier ist, wie das funktioniert: IResult hat eine Execute-Methode und eine Abgeschlossene Veranstaltung. Caliburn.Micro packt die IEnumerator-aus dem Aufruf HandleButtonClick() und übergibt ihn in eine Coroutine.BeginExecute-Methode. Die BeginExecute-Methode beginnt, Durchlaufen die IResults. Wenn die ersten IResult zurückgegeben, wird die Ausführung angehalten wird, innerhalb HandleButtonClick(), und BeginExecute() fügt einen Ereignis-handler auf das Completed-Ereignis und ruft Execute () auf. IResult.Execute() ausführen können, entweder eine synchrone oder eine asynchrone Aufgabe und feuert das Completed-Ereignis, wenn es fertig ist.
LoginResult sieht ungefähr so aus:
Kann es helfen, etwas einzurichten, wie dies und Schritt für Schritt durch die Ausführung zu beobachten, was vor sich geht.
Hoffe, das jemand hilft! Ich habe es wirklich genossen die Erkundung der verschiedenen Möglichkeiten, die Ausbeute verwendet werden kann.
InformationsquelleAutor der Antwort Adam W. McKinley
Die zwei Teile des Codes sind wirklich zwei verschiedene Dinge. Die erste version wird pull-Mitglieder, wie Sie Sie benötigen. Die zweite version geladen werden, die alle die Ergebnisse in den Speicher vor Sie beginnen, etwas zu tun.
Gibt es keine richtige oder falsche Antwort auf diese ein. Welche vorzuziehen ist, hängt nur von der situation. Zum Beispiel, wenn es gibt eine Grenze der Zeit, die Sie haben, um Ihre Abfrage, und Sie müssen etwas tun, semi-kompliziert mit den Ergebnissen, die zweite version könnte besser sein. Aber hüten Sie sich vor großen resultsets, vor allem, wenn Sie diesen code ausführen im 32-bit-Modus. Ich habe gebissen worden von OutOfMemory-Ausnahmen mehrere Male, wenn Sie diese Methode.
Den Schlüssel Sache im Auge zu behalten ist, obwohl dies: die Unterschiede in der Effizienz. So, Sie sollten wahrscheinlich gehen mit, je nachdem was man macht den code einfacher, und ändern Sie es nur nach Profilierung.
InformationsquelleAutor der Antwort Jason Baker
Ausbeute hat zwei große verwendet
Hilft es, benutzerdefinierte iteration mit heraus erzeugen der temporären Sammlungen. ( das laden aller Daten und looping)
Es hilft, das zu tun stateful iteration. ( streaming)
Unten ist ein einfaches video, das ich erstellt habe, mit voller demonstration zur Unterstützung der beiden oben genannten Punkte
http://www.youtube.com/watch?v=4fju3xcm21M
InformationsquelleAutor der Antwort Shivprasad Koirala
Dies ist, was Chris Sells erzählt über diese Aussagen in Die Programmiersprache C# ;
InformationsquelleAutor der Antwort Teoman shipahi
Dies ist ein bisschen neben dem Punkt, aber da ist die Frage tagged best practices " ich werde gehen Sie vor und werfen Sie in meine zwei Cent. Für diese Art der Sache, die ich stark bevorzugen, um es in eine Immobilie:
Sicher, es ist ein wenig mehr-Kessel-Platte, sondern der code, der verwendet, dies sieht viel sauberer aus:
vs
Hinweis: ich würde das nicht für alle Methoden, die eine Weile dauern kann, um Ihre Arbeit zu tun.
InformationsquelleAutor der Antwort Mark A. Nicolosi
Vorausgesetzt Ihre Produkte LINQ-Klasse verwendet eine ähnliche Ausbeute für das auflisten der/die Iteration, die erste version ist effizienter, da Ihr nur nachgeben, ein Wert, der jedes mal seine Iteration.
Das zweite Beispiel ist die Umwandlung der enumerator/iterator auf eine Liste mit der ToList () - Methode. Dies bedeutet, es manuell iteriert über alle Elemente des Enumerators und dann gibt eine flache Liste.
InformationsquelleAutor der Antwort Soviut
Und was ist das?
Ich denke, das ist viel sauberer. Ich habe nicht VS2008 bei der hand, um zu prüfen, obwohl.
In jedem Fall, wenn Produkte, die IEnumerable implementiert (wie es scheint - es wird in einer foreach-Anweisung), würde ich es zurückgeben direkt.
InformationsquelleAutor der Antwort petr k.
Rendite kann sehr mächtig für algorithmen, wo Sie brauchen, zu Durchlaufen Millionen von Objekten. Betrachten Sie das folgende Beispiel, wo Sie brauchen, um zu berechnen, mögliche Ausflüge für rideshare. Zuerst erzeugen wir mögliche Ausflüge:
Iteriere durch jede Reise:
Wenn Sie die Liste statt Rendite, müssen Sie die Zuweisung von 1 million Objekten auf den Speicher (~190 MB) und diesem einfachen Beispiel wird nehmen ~1400ms zu laufen. Wenn Sie jedoch mit dem Ertrag, den Sie nicht brauchen, um alle diese temp-Objekte im Speicher und bekommen Sie deutlich schneller Algorithmus die Geschwindigkeit: in diesem Beispiel wird nur ~400ms ausgeführt ohne memory-Verbrauch überhaupt.
InformationsquelleAutor der Antwort Andzej Maciusovic
Zurückgeben der Liste direkt. Vorteile:
Die Liste ist wiederverwendbar. (der iterator nicht)nicht wirklich wahr, vielen Dank JonVerwenden Sie den iterator (Ertrag) aus, wenn Sie denken, dass Sie wahrscheinlich nicht haben, Durchlaufen Sie alle den Weg an das Ende der Liste, oder wenn es kein Ende hat. Zum Beispiel, der client Aufruf wird die Suche für das erste Produkt, das erfüllt manche Prädikat, könnten Sie überlegen, mit Hilfe der iterator, aber das ist ein erfundenes Beispiel, und es gibt wahrscheinlich bessere Wege, es zu erreichen. Grundsätzlich, wenn Sie im Voraus wissen, dass die gesamte Liste berechnet werden müssen, tun Sie es einfach nach vorne. Wenn Sie denken, dass es nicht wird, dann erwägen Sie die Verwendung der iterator-version.
InformationsquelleAutor der Antwort recursive
Ich würde version 2 verwendet haben, den code in diesem Fall. Da haben Sie die volle Liste von Produkten zur Verfügung, und das ist, was erwartet vom "Verbraucher", der diese Methode aufrufen, wäre es erforderlich, senden Sie die vollständige Informationen an den Aufrufer zurück.
Wenn der Aufrufer dieser Methode erfordert "eine" information zu einem Zeitpunkt, und der Verbrauch die nächsten Informationen on-demand-basis, dann wäre es vorteilhaft zu verwenden, Rendite die machen sicher, dass der Befehl der Ausführung wird an den Aufrufer zurückgegeben, wenn eine Einheit, die Informationen zur Verfügung stehen.
Einige Beispiele, wo man nutzen könnte Rendite ist:
Ihre Fragen zu beantworten, müsste ich die version 2.
InformationsquelleAutor der Antwort IntelligentBinary
Die Rendite keyphrase wird verwendet, um den Zustand zu verwalten Maschine für eine bestimmte Sammlung. Überall dort, wo die CLR sieht die Rendite keyphrase verwendet wird, die CLR implementiert ein Enumerator-Muster auf das Stück code. Diese Art der Umsetzung hilft den Entwickler von aller Art der Sanitär, die wir sonst zu tun haben, in Abwesenheit des Schlüsselworts.
Angenommen, wenn die Entwickler ist die Filterung einer Sammlung, die Iteration, obwohl die Sammlung und dann extrahieren Sie diese Objekte in einigen neuen Kollektion. Diese Art der Heizung ist ziemlich monoton.
Mehr über das Stichwort an diesem Artikel.
InformationsquelleAutor der Antwort Vikram
Die Verwendung von Ertrag ist ähnlich zu dem Schlüsselwort zurück, außer, dass wird es wieder ein generator. Und die generator Objekt wird nur Durchlaufen einmal.
Ertrag hat zwei Vorteile:
Es ist ein weiteres klares Erklärung vielleicht helfen Sie.
InformationsquelleAutor der Antwort 123