Was sind die Hauptunterschiede zwischen IEnumerable
Count()
und Length
?
Was sind die Hauptunterschiede zwischen IEnumerable
Count()
und Length
?
Antworten:
Wenn Sie Count on aufrufen IEnumerable<T>
, gehen Sie davon aus, dass Sie sich auf die Erweiterungsmethode Count
on beziehen System.Linq.Enumerable
. Length
ist keine Methode für IEnumerable<T>
, sondern eine Eigenschaft für Array-Typen in .Net wie int[]
.
Der Unterschied ist die Leistung. Bei der Length
Immobilie handelt es sich garantiert um eine O (1) -Operation. Die Komplexität der Count
Erweiterungsmethode hängt vom Laufzeittyp des Objekts ab. Es wird versucht, mehrere Typen zu verwenden, die die Suche nach O (1) -Längen wie ICollection<T>
über eine Count
Eigenschaft unterstützen. Wenn keine verfügbar sind, werden alle Elemente aufgelistet und gezählt, die eine Komplexität von O (N) haben.
Zum Beispiel
int[] list = CreateSomeList();
Console.WriteLine(list.Length); // O(1)
IEnumerable<int> e1 = list;
Console.WriteLine(e1.Count()); // O(1)
IEnumerable<int> e2 = list.Where(x => x <> 42);
Console.WriteLine(e2.Count()); // O(N)
Der Wert e2
wird als C # -Iterator implementiert, der die O (1) -Zählung nicht unterstützt. Daher Count
muss die Methode die gesamte Sammlung auflisten, um zu bestimmen, wie lange sie dauert .
string[]
Arrays mit beispielsweise 5-10 Elementen ... würden Sie dann eine Array.Length
Leistung vorschlagen ?
Count()
da das Array implementiert wird ICollection<T>
- aber es ist weniger effizient als die Length
direkte Verwendung . Wenn Sie bereits wissen, dass es sich um ein Array handelt, würde ich es Length
nicht aus Effizienzgründen verwenden, sondern weil ich es als idiomatischer ansehen würde. Ebenso würde ich die Count
Eigenschaft für alles verwenden, was einen Typ zur Kompilierungszeit hatte ICollection<T>
. Ich würde anrufen, Count()
wenn der Ausdruck zur Kompilierungszeit vom Typ ist IEnumerable<T>
, auch wenn ich weiß, dass es sich wirklich um ein Array hinter den Kulissen handelt.
System.Array
eine viel grundlegendere Klasse war (ähnlich wie object
); Nach dem Überprüfen von MSDN werden jedoch mehrere "sammlungsbezogene" Schnittstellen implementiert. Ich bin ein Web - Programmierer so „Count“ gemacht semantischen Sinne (wie header
vs. div
in HTML) auf den ersten, aber ich verstehe Ihren Standpunkt , da sie explizit eine ist string[]
zur Compile-Zeit Length
mehr Sinn macht.
while(list.Count() > 0)
einige Logiken mit Aktionen zum Hinzufügen / Entfernen.
Kleine Ergänzung zu Jon Skeets Kommentar.
Hier ist der Quellcode der Count()
Erweiterungsmethode:
.NET 3:
public static int Count<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
ICollection<TSource> is2 = source as ICollection<TSource>;
if (is2 != null)
{
return is2.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num++;
}
}
return num;
}
.NET 4:
public static int Count<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
ICollection<TSource> is2 = source as ICollection<TSource>;
if (is2 != null)
{
return is2.Count;
}
ICollection is3 = source as ICollection;
if (is3 != null)
{
return is3.Count;
}
int num = 0;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
num++;
}
}
return num;
}
ICollection
Typ zu suchen. (Da das auch eine Count
Eigenschaft hat.)
use
man die Error
Klasse erhält, die diese Methode verwendet? Ich kann es anscheinend nirgendwo auf MSDN finden, außer in der JScript-Dokumentation.
Die Länge ist eine feste Eigenschaft, z. B. eines eindimensionalen Arrays oder Strings. Es ist also nie eine Zähloperation erforderlich (mehrdimensionale Arrays haben eine Größe aller Dimensionen multipliziert). O (1) -Operation bedeutet hier, dass die Abrufzeit immer gleich ist, egal wie viele Elemente es gibt. Eine lineare Suche wäre (im Gegensatz dazu) O (n).
Die Count-Eigenschaft für ICollections (z. B. List und List <T>) kann sich ändern. Sie muss daher entweder beim Hinzufügen / Entfernen aktualisiert werden oder wenn Count angefordert wird, nachdem die Collection geändert wurde. Hängt von der Implementierung des Objekts ab.
Die Count () -Methode von LINQ iteriert grundsätzlich JEDES MAL, wenn sie aufgerufen wird (außer wenn das Objekt ein ICollection-Typ ist, wird die ICollection.Count-Eigenschaft angefordert).
Beachten Sie, dass IEnumerables häufig nicht bereits definierte Objektsammlungen (wie Listen, Arrays, Hashtabellen usw.) sind, sondern mit Hintergrundoperationen verknüpft sind, die bei jeder Anforderung Ergebnisse generieren (als verzögerte Ausführung bezeichnet).
Normalerweise haben Sie eine SQL-ähnliche LINQ-Anweisung wie diese (die typische Anwendung der verzögerten Ausführung):
IEnumerable<Person> deptLeaders =
from p in persons
join d in departments
on p.ID equals d.LeaderID
orderby p.LastName, p.FirstName
select p;
Dann gibt es Code wie diesen:
if (deptLeaders.Count() > 0)
{
ReportNumberOfDeptLeaders(deptLeaders.Count());
if (deptLeaders.Count() > 20)
WarnTooManyDepartmentLeaders(deptLeaders.Count());
}
Wenn also eine Warnung für zu viele Abteilungsleiter ausgegeben wird, durchläuft .NET VIER MAL die Personen, vergleicht sie mit den Abteilungsleitern, sortiert sie nach Namen und zählt dann die Ergebnisobjekte.
Dies ist nur dann der Fall, wenn Personen und Abteilungen voreingestellte Wertsammlungen sind und keine Abfragen selbst.
.Count() > 0
das das gleiche ist wie .Any()
.
.Any()
effizienter als .Count() > 0
damals? Übrigens beschwert sich Resharper immer darüber .Count() > 0
. Deshalb spreche ich es mit Zuversicht an.
List<T>
hat keine Length-Eigenschaft - es hat eine Count-Eigenschaft. Arrays haben eineLength
obwohl.Count
wird inICollection
undICollection<T>
(dieIList<T>
erweitert) angegeben.