In meiner ASP.net MVC4-Webanwendung verwende ich IEnumerables und versuche, dem Mantra zu folgen, um die Schnittstelle zu programmieren, nicht die Implementierung.
Return IEnumerable(Of Student)
vs
Return New List(Of Student)
Ich soll List und nicht IEnumerable verwenden, da Listen die Ausführung der Abfrage erzwingen und IEumerable nicht.
Ist das wirklich die beste Vorgehensweise? Gibt es eine Alternative? Ich fühle mich seltsam, wenn ich konkrete Objekte verwende, bei denen eine Schnittstelle verwendet werden könnte. Ist mein seltsames Gefühl berechtigt?
.net
programming-practices
asp.net-mvc
entity-framework
Rowan Freeman
quelle
quelle
Antworten:
Es gibt
ToList()
Situationen, in denen es wichtig sein kann, eine linq-Abfrage durchzuführen, um sicherzustellen, dass Ihre Abfragen zum gewünschten Zeitpunkt und in der von Ihnen erwarteten Reihenfolge ausgeführt werden. Diese Szenarien sind jedoch selten und nichts, worüber man sich zu viele Sorgen machen sollte, bis sie tatsächlich auf sie treffen.Um es kurz zu machen: Verwenden
IEnumerable
Sie diese Option immer dann , wenn Sie nur Iterationen benötigen,IList
wenn Sie direkt indizieren müssen und ein Array mit dynamischer Größe benötigen (wenn Sie ein Array mit fester Größe indizieren müssen, verwenden Sie einfach ein Standardarray).Wie für die Ausführungszeit Sache, können Sie immer eine Liste als verwenden
IEnumerable
Variable, so fühlen sich frei , eine RückkehrIEnumerable
ein , indem Sie.ToList();
oder in einem Parameter , der als einen PassIEnumerable
durch die Ausführung.ToList()
auf derIEnumerable
rechten dann Kraft Ausführung und dort. Achten Sie nur darauf, dass Sie bei jeder erzwungenen Ausführung.ToList()
nicht an derIEnumerable
Variablen festhalten, mit der Sie dies gerade getan haben, und sie erneut ausführen. Andernfalls werden Sie die Iterationen in Ihrer LINQ-Abfrage unnötigerweise verdoppeln.In Bezug auf MVC gibt es hier wirklich nichts Besonderes zu beachten. Es wird den gleichen Regeln für die Ausführungszeit folgen wie der Rest von .NET. Ich glaube, Sie haben jemanden, der durch die verzögerte Ausführungssemantik in der Vergangenheit verwirrt war und MVC die Schuld dafür gibt, dass dies irgendwie verwandt ist, aber es ist nicht. Die Semantik der verzögerten Ausführung verwirrt zunächst alle (und auch noch für eine Weile danach; sie kann etwas schwierig sein). Machen Sie sich aber auch hier keine Sorgen, bis Sie wirklich sicherstellen möchten, dass eine LINQ-Abfrage nicht zweimal ausgeführt wird oder in einer bestimmten Reihenfolge im Vergleich zu anderem Code ausgeführt werden muss. Weisen Sie dann Ihre Variable sich selbst zu. ToList () Hinrichtung zu erzwingen, und Sie werden in Ordnung sein.
quelle
List
--passing a nicht einmal verwenden, um zuList
implizieren, dass der Inhalt der Liste geändert wird. Wenn Sie eine Sammlung zurückgeben möchten, verwenden SieIReadOnlyCollection
.List
Dient zur Verwendung in Methoden und zum Austausch zwischen Methoden, die die Liste ändern. Das ist es!Es gibt zwei Probleme.
Wenn die "Process Data" -Schleife erreicht ist, ist die Abfrage möglicherweise nicht mehr gültig. Wenn die Abfrage beispielsweise für einen DataContext ausgeführt wird, der bereits freigegeben wurde, löst Ihr Code eine Ausnahme aus. Dies ist sehr verwirrend, wenn Sie eine Abfrage in einem anderen Kontext als dem, in dem Sie sie erstellt haben, verarbeiten.
Ein sekundäres Problem ist, dass Ihre Verbindung nicht freigegeben wird, bis die Schleife "Process Data" abgeschlossen ist. Dies ist nur dann ein Problem, wenn "Process Data" komplex ist. Dies wird unter http://msdn.microsoft.com/en-us/library/bb386929.aspx erwähnt :
Aus diesen Gründen sollten Sie sicherstellen, dass die Abfrage tatsächlich ausgeführt wird, z
ToList()
. B. durch einen Anruf . Wie Jimmy vorschlägt, hindert Sie nichts daran, Ihre Liste als IEnumerable zurückzugeben.Im Allgemeinen empfehle ich, das mehrmalige Durchlaufen eines IEnumerable zu vermeiden. Unter der Annahme, dass die Konsumenten Ihres Codes diese Regel befolgen, ist es meines Erachtens nicht bedenklich, dass jemand die Datenbank zweimal durch zweimaliges Ausführen der Abfrage erreicht.
quelle
Ein weiterer Vorteil der Aufzählung der
IEnumerable
frühen Ausnahmen ist, dass sie an der entsprechenden Stelle ausgelöst werden. Dies unterstützt das Debuggen.Wenn Sie beispielsweise in einer Ihrer Razor-Ansichten eine Deadlock-Ausnahme festgestellt haben, ist dies nicht so eindeutig, als ob die Ausnahme während einer Ihrer Datenzugriffsmethoden aufgetreten wäre.
quelle
IEnumerable
zurückgibt, der werfen kann, macht wahrscheinlich einen Fehler. VerzögerteIEnumerable
Methoden sollten in zwei aufgeteilt werden: Eine nicht verzögerte Methode prüft die Parameter und richtet sie ein und löst sie gegebenenfalls aus (z. B. aufgrund eines Null-Arguments). Dann gibt er einen Aufruf an die privaten Implementierung , die sich verschoben. Ich glaube nicht , meine Kommentare in völligem Widerspruch zu Ihrer Antwort sind, aber denke , dass Sie in Ihrer Antwort einen wichtigen Aspekt ausgelassen haben, die das ist semantische Bedeutung der VerwendungIEnumerable
gegen einList
(Mutation) vs.IReadOnlyCollection
(keinen Nutzen Aufschub) .