C # List vs IEnumerable Performance Frage
-
06-07-2019 - |
Frage
Hallo nehme diese 2 Methoden:
private List<IObjectProvider> GetProviderForType(Type type)
{
List<IObjectProvider> returnValue = new List<IObjectProvider>();
foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
{
if ((provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
{
returnValue.Add(provider.Value);
}
}
return returnValue;
}
private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
if ((provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
yield return provider.Value;
}
Welches ist schneller? Als ich bei der ersten Methode anschaue, sehe ich, dass der Speicher für Liste zugeordnet ist, was meiner Meinung nach ist es nicht erforderlich. Die IEnumerable Methode scheint mir schneller zu sein.
Zum Beispiel: Angenommen, Sie rufen
int a = GetProviderForType(myType).Count;
int b = GetProviderForType1(myType).Count();
Nun wird ein weiteres Problem ist, gibt es einen Unterschied in der Leistung zwischen diesen 2 oben?
Was denken Sie?
Lösung
In diesem speziellen Fall des IEnumerable<T>
Formular wird effizienter, da Sie nur muß die Zählung wissen. Es gibt keinen Grund, die Daten bei der Speicherung, Ändern der Größe Puffer usw., wenn Sie nicht benötigen.
Wenn Sie die Ergebnisse benötigt wieder aus irgendeinem Grund zu verwenden, würde die List<T>
Form effizienter sein.
Beachten Sie, dass sowohl die Count()
Erweiterung Methode und die Count
Eigenschaft wird für List<T>
effizient sein wie die Umsetzung der Count()
überprüft, ob die Zielsequenz ICollection<T>
implementiert und verwendet die Count
Eigenschaft, wenn so.
Eine weitere Option, die auch sein sollte mehr effizient (wenn auch nur kurz) wäre, die Überlastung von Count
zu nennen, die einen Delegierten nimmt:
private int GetProviderCount(Type type)
{
return _objectProviders.Count(provider =>
(provider.Key.IsAssignableFrom(type)
|| type.IsAssignableFrom(provider.Key))
&& provider.Value.SupportsType(type));
}
Das wird die zusätzliche Ebene der Indirekt durch die Where
und Select
Klauseln entstehen vermeiden.
(wie Marc sagt, für kleine Datenmengen werden die Leistungsunterschiede wahrscheinlich vernachlässigbar sein sowieso.)
Andere Tipps
Die genaue Antwort wie diese Fragen können in Abhängigkeit von einer Vielzahl von Faktoren variieren, und kann weiter verändern, wie die CLR entwickelt. Der einzige Weg, um sicher zu sein, ist es zu messen, -. Und beachten Sie, dass, wenn die Differenz klein ist im Vergleich zu der Operation dies in erscheinen wird, dann sollten Sie die meisten lesbar, wartbar Art und Weise des Schreibens pick it
Und in diesem Sinne, könnten Sie auch versuchen wollen:
private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
return _objectProviders.Where(provider =>
provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
.Select(p => p.Value);
}
Sie können sich auch eine Menge an Flexibilität geben, indem IEnumerable<T>
zurückkehren und dann die ToList
Extension-Methode verwenden, wenn Sie „Snapshot“ wollen die Ergebnisse in einer Liste an. Dies wird wiederholte Auswertung des Codes vermeiden, um die Liste zu generieren, wenn Sie es mehrfach untersuchen müssen.
Ein wichtiger Teil dieser Frage ist: „Wie groß ist die Daten“? Wie viele Zeilen ...
Für kleine Datenmengen, die Liste ist in Ordnung - es wird vernachlässigbare Zeit eine ausreichend große Liste zuzuordnen, und es wird nicht oft (keine, wenn Sie es sagen können, wie groß im Voraus zu sein) die Größe <. / p>
Dies ist jedoch nicht Maßstab zu riesigen Datenmengen; es scheint unwahrscheinlich, dass Ihr Provider Tausende von Schnittstellen unterstützt, so dass ich würde nicht sagen, es ist erforderlich , um dieses Modell zu gehen -. aber es wird nicht sehr groß schaden
Natürlich können Sie LINQ verwenden, auch:
return from provider in _objectProviders
where provider.Key.IsAssignableFrom(type) ...
select provider.Value;
Dies ist auch der latente yield
Ansatz unter der Decke ...
Der wesentliche Unterschied zwischen IEnumerable und IList:
IEnumerable: Implementiert Movenext, Reset, Get Aktuelle Methoden und gibt einen Typ von IEnumerator iterieren Durch Aufzeichnungen.
IList: Mach die IEnumerable-Schnittstelle sowie es auch eine Sammlung von nicht-generischen Objekten, die durch einen Index zugegriffen können so IEnumerable + ICollection (Manipulation von Daten) und Hinzufügen, Entfernen, Einfügen (in bestimmtem Index) sind nützlich Methoden implementiert durch IList.
Nach meiner Meinung IEnumerable auf den Code der Suche ist effizienter, aber Rückkehr Liste ist auch nützlich, wenn Sie einige Manipulation mit Daten tun wollen, und wenn Sie nur durch die Daten iterieren wollen, dann IEnumerable vorzuziehen.