"Möglich, mehrere enumeration von IEnumerable" vs "- Parameter können deklariert werden, mit dem Basistyp"
In Resharper 5, der folgenden code-led zur Warnung "Parameter deklariert werden können mit dem Basis-Typ" für list
:
public void DoSomething(List<string> list)
{
if (list.Any())
{
//...
}
foreach (var item in list)
{
//...
}
}
In Resharper 6, dies ist nicht der Fall. Allerdings, wenn ich die Methode ändern, um die folgenden, noch bekomme ich diese Warnung:
public void DoSomething(List<string> list)
{
foreach (var item in list)
{
//...
}
}
Der Grund dafür ist, dass in dieser version, ist nur einmal aufgezählt, so ändern Sie ihn auf IEnumerable<string>
wird nicht automatisch einführen, eine weitere Warnung.
Nun, wenn ich die erste version manuell zu verwenden IEnumerable<string>
statt einer List<string>
, ich werde diese Warnung ("mehrere Mögliche Aufzählung von IEnumerable") auf beide vorkommen von list
im Körper der Methode:
public void DoSomething(IEnumerable<string> list)
{
if (list.Any()) //<- here
{
//...
}
foreach (var item in list) //<- and here
{
//...
}
}
Verstehe ich, warum, aber ich Frage mich, wie man dieses Problem lösen Warnung, vorausgesetzt, dass die Methode wirklich nur braucht ein IEnumerable<T>
und nicht ein List<T>
denn ich will einfach nur zum aufzählen der Elemente und ich will nicht, um die Liste zu ändern.
Hinzufügen eines list = list.ToList();
am Anfang der Methode ist die Warnung Weg gehen:
public void DoSomething(IEnumerable<string> list)
{
list = list.ToList();
if (list.Any())
{
//...
}
foreach (var item in list)
{
//...
}
}
Ich verstehe, warum, macht die Warnung geht Weg, aber es sieht ein bisschen aus wie ein hack zu mir...
Irgendwelche Vorschläge, wie zu lösen, die Warnung besser und noch verwenden die meisten allgemein Typ möglich in der Signatur der Methode?
Die folgenden Probleme sollten alle gelöst werden, für eine gute Lösung:
- Kein Aufruf
ToList()
innerhalb der Methode, weil es eine Auswirkung auf die Leistung - Keine Verwendung von
ICollection<T>
oder sogar mehr spezialisierte Schnittstellen/Klassen, da Sie die Semantik der Methode, aus Sicht der Anrufer. - Keine mehrfache Iterationen über eine
IEnumerable<T>
und damit zu riskieren, Zugriff auf eine Datenbank mehrere Male oder ähnliches.
Hinweis: ich bin mir bewusst, dass dies nicht eine Resharper Problem, und dadurch, dass ich nicht wollen, um diese Warnung zu unterdrücken, sondern beheben Sie die zugrunde liegende Ursache, wie die Warnung legitim ist.
UPDATE:
Bitte don ' T care about Any
und die foreach
. Ich brauche nicht zu helfen in der Zusammenführung dieser Aussagen haben nur eine Aufzählung der enumerable.
Es könnte wirklich alles sein, was in dieser Methode zählt die enumerable-mehrfach!
InformationsquelleAutor der Frage Daniel Hilgarth | 2011-07-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Generell, was Sie benötigen, ist ein state-Objekt, in das Sie DRÜCKEN können die Elemente (innerhalb einer foreach-Schleife), und aus der Sie dann Ihre endgültige Ergebnis.
Den Nachteil der enumerable-LINQ-Operatoren ist, dass Sie aktiv aufzählen, die Quelle anstelle der Annahme der posten geschoben, damit Sie Ihren Anforderungen nicht gerecht werden.
Wenn Sie z.B. nur müssen die minimum-und maximum-Werte einer Sequenz von 1'000'000 integers, die Kosten $1'000 im Wert von CPU-Zeit zu Holen, Sie schreiben etwas wie dieses:
In der Tat, Sie nur re-implementiert die Logik für die Min() und Max() Operatoren. Das ist natürlich leicht, aber Sie sind nur Beispiele für beliebige komplexe Logik, die Sie sonst leicht Ausdrücken, in einem LINQish Weg.
Die Lösung kam mir auf der gestrigen Nachtwanderung: wir SCHIEBEN müssen... das ist REAKTIV! Alle die geliebten Operatoren, gibt es auch in einer reaktiven version gebaut für die push-Paradigma. Sie können miteinander verkettet werden, wie die Komplexität, die Sie brauchen, genauso wie Ihre enumerable-Pendants.
So die min - /max-Beispiel läuft darauf hinaus:
InformationsquelleAutor der Antwort tinudu
Diese Klasse wird Ihnen einen Weg zu splitten, den ersten Punkt aus der Aufzählung und dann ein IEnumerable für den rest der Aufzählung, ohne dass Sie eine doppelte Aufzählung, so dass die potentiell bösen Leistungseinbruch. Es ist Verwendung ist wie dieses (wo T ist unabhängig von der Art, die Sie aufzählen):
Hier ist die Klasse selbst:
Bedeutet dies voraussetzen, dass die IEnumerable hat mindestens ein element, um zu starten. Wenn Sie möchten, um mehr von dem tun, ein FirstOrDefault-setup-Typ, den Sie benötigen, um die Ausnahme zu fangen, die sonst weggeworfen werden dem Konstruktor übergeben.
InformationsquelleAutor der Antwort srm
Sollten Sie wahrscheinlich eine
IEnumerable<T>
- und ignorieren die "mehrere Iterationen" Warnung.Diese Meldung warnt Sie, dass, wenn Sie einen ruhigen enumerable (wie ein iterator oder eine kostspielige LINQ-Abfrage) auf Ihrer Methode, Teile der iterator ausgeführt wird, zweimal.
InformationsquelleAutor der Antwort SLaks
Es ist keine perfekte Lösung, wählen Sie eine entsprechend der situation.
Die erste Lösung (ToList) ist wohl die "richtige" für eine öffentliche Methode, die könnten arbeiten an Enumerable.
Können Sie ignorieren, Resharper Fragen, die Warnung legitim ist in einem Allgemeinen Fall aber falsch sein kann, die in Ihrer spezifischen situation. Vor allem, wenn die Methode ausschließlich für den internen Gebrauch und haben Sie die volle Kontrolle über Anrufer.
InformationsquelleAutor der Antwort Guillaume
Gibt es eine Allgemeine Lösung, die sowohl Resharper Warnungen: die fehlende Garantie für die repeat-Fähigkeit von IEnumerable, und die Liste Basisklasse (oder potenziell teuer ToList() workaround).
Erstellen Sie eine spezialisierte Klasse, I. E "RepeatableEnumerable", Implementierung von IEnumerable, mit "GetEnumerator()" implementiert, mit der folgenden Logik Gliederung:
Ertrag alle Elemente, die sich bereits erhoben, so weit von der inneren Liste.
Wenn Sie die verpackte enumerator hat mehr Elemente,
Während die gewickelt enumerator bewegen kann, um das nächste Element,
Holen Sie sich das aktuelle Element aus dem inneren enumerator.
Fügen Sie das aktuelle Element der inneren Liste.
Rendite auf das aktuelle Element
Markieren Sie die innere enumerator, dass Sie keine Elemente mehr.
Hinzufügen Erweiterung Methoden und entsprechende Optimierungen, wo die gewickelten parameter ist bereits wiederholbar. Resharper nicht mehr markieren Sie die angezeigten Warnungen auf den folgenden code:
Mit ein wenig Arbeit, können Sie auch aktivieren, RepeatableEnumerable in LazyList, eine vollständige Implementierung der IList. Das würde den Rahmen dieses spezielle problem obwohl. 🙂
UPDATE: Code-Implementierung angefordert, die in Kommentaren-nicht sicher, warum der ursprüngliche PDL war nicht genug, aber in jedem Fall, die folgenden originalgetreu implementiert den Algorithmus, den ich vorgeschlagen (Meine eigene Implementierung implementiert die vollständige IList-Schnittstelle; das ist ein bisschen über den Rahmen will ich release hier... 🙂 )
InformationsquelleAutor der Antwort T.Tobler
Merke ich, diese Frage ist alt und schon als beantwortet markiert, aber ich war überrascht, dass niemand vorgeschlagen manuell iteriert enumerator:
Scheint viel einfacher als die anderen Antworten hier.
InformationsquelleAutor der Antwort Jeff G
Warum nicht:
Update: ich Persönlich würde nicht drastisch ändern Sie den code, um zu bekommen eine Warnung wie diese. Ich würde einfach deaktivieren Sie die Warnung und fahren auf. Die Warnung ist, dass Sie zum ändern der Allgemeinen Strömung der code um es besser zu machen; wenn Sie nicht machen den code besser (und wohl auch macht es schlimmer) Adresse die Warnung; dann den Punkt für die Warnung ausgelassen wird.
Beispiel:
InformationsquelleAutor der Antwort Peter Ritchie
UIMS* - Grundsätzlich ist es kein großer lösen. IEnumerable<T> verwendet, um die "sehr grundlegende Sache, die Sie repräsentiert ein Bündel von Sachen der gleichen Art, so verwenden Sie in der Methode sigs Richtig ist." Es hat jetzt auch zu einer "Sache, die möglicherweise bewerten, hinter den kulissen, und es kann eine Weile dauern, so dass Sie jetzt immer Angst haben."
Es ist, als wenn IDictionary plötzlich wurden erweitert um Unterstützung für verzögertes laden von Werten, die über eine LazyLoader Eigenschaft vom Typ Func<TKey,TValue>. Tatsächlich, das wäre nett zu haben, aber nicht so ordentlich ist, Hinzugefügt werden, IDictionary, weil jetzt, jedes mal erhalten wir eine IDictionary wir uns sorgen machen müssen. Aber das ist, wo wir sind.
So würde es scheinen, dass, wenn eine Methode nimmt ein IEnumerable und evals es zweimal, immer force eval per ToList()" ist das beste, was Sie tun können. Und schöne Arbeit von Jetbrains, um uns diese Warnung.
*(Es sei denn, ich bin Fehlt Etwas . . . gerade gemacht aber es scheint nützlich)
InformationsquelleAutor der Antwort Bean Taxi
Vorsichtig sein bei der Annahme enumerables in Ihrer Methode. Die "Warnung" für den Typ ist nur ein Hinweis, die Aufzählung Warnung ist eine echte Warnung.
Jedoch in Ihrer Liste aufgezählt werden mindestens zwei mal, da Sie eine und dann eine foreach. Wenn Sie fügen Sie eine
ToList()
Ihren enumeration aufgezählt werden drei mal - entfernen Sie die ToList().Ich würde vorschlagen, setzen resharpers Warnung Einstellungen für die Basis-Typ, Hinweis. So haben Sie immer noch einen Hauch (grün unterstreichen) und die Möglichkeit zu quickfix (alt+enter) und keine "Warnungen" in Ihrer Datei.
Sollten Sie darauf achten, ob die Aufzählung der IEnumerable-Schnittstelle ist eine teure Aktion, wie das laden etwas aus der Datei oder Datenbank, oder, wenn Sie eine Methode, die berechnet die Werte und nutzt Rendite. In diesem Fall tun
ToList()
oderToArray()
ersten laden/berechnen Sie alle Daten nur EINMAL.InformationsquelleAutor der Antwort Zebi
Könnten Sie
ICollection<T>
(oderIList<T>
). Es ist weniger spezifisch alsList<T>
aber leiden nicht die mehrfach-enumeration problem.Trotzdem würde ich eher auf
IEnumerable<T>
in diesem Fall. Sie können auch prüfen, Refactoring der code zum auflisten nur einmal.InformationsquelleAutor der Antwort CodesInChaos
Verwenden IList als Ihren parameter-Typ statt IEnumerable - Typ IEnumerable hat eine andere Semantik zur Liste in der Erwägung, dass IList hat die gleiche
IEnumerable werden könnte, basiert auf einem non-seekable stream, die ist, warum man die Warnungen
InformationsquelleAutor der Antwort Richard Blewett
Können Sie die Iteration nur einmal :
InformationsquelleAutor der Antwort Guillaume
Es ist etwas, das niemand gesagt hatte bevor (@Zebi). Jede() bereits wiederholt versucht, suchen Sie nach dem element. Beim Aufruf von ToList(), wird die Iteration als auch, um eine Liste zu erstellen. Die ursprüngliche Idee der Verwendung von IEnumerable wird nur Durchlaufen, alles andere provoziert eine iteration, um Sie zu führen. Sie sollten versuchen, innerhalb einer einzigen Schleife, alles tun.
Und gehören in das Ihre .Jede () - Methode.
wenn Sie übergeben eine Liste von Aktion, die in Ihrer Methode würden Sie einen Reiniger Durchlaufen einmal code
InformationsquelleAutor der Antwort marcelo-ferraz