2010-12-29 14 views
3

Von den folgenden 2 Möglichkeiten, eine Sammlung aufzuzählen, sollte man gegenüber dem anderen OR vorgezogen werden, sind beide in Bezug auf die Leistung gleich (dh, ToList() Konvertierung ist in der zweiten Ansatz beteiligt)Verschiedene Möglichkeiten, eine Sammlung zu nummerieren

foreach(SomeType st in Collection) 
{ 
    //Do something 
} 


Collection.OfType<SomeType>.ToList().ForEach() 

Gibt es einen anderen Weg (außer die Verwendung von Wiederwahl)?

EDIT

Wie wäre dieses Szenario?

class SomeType : IMyType 
{ 
} 

class OtherType : IMyType 
{ 
} 

class SomeCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable 
{ 
} 

Anbetracht MyTypes ist eine Eigenschaft in einer Klasse mit Typ SomeCollection<IMyType> die folgenden zwei Ansätze gleich?

foreach(IMyType mt in MyTypes) 
{ 
    if(IMyType is SomeType) 
    return; 
} 

ODER

if(MyTypes.OfType<SomeType>.Any()) 
    return; 
+0

Welche verwendet werden sollte, hängt wirklich davon ab, was Sie versuchen zu tun. – Oded

+0

Abhängig von der Sammlung (und wenn sie CollectionBase erweitert) können Sie einfach auf die IList-Schnittstelle und die ForEach-Methode verweisen und darüber iterieren (keine Konvertierung in eine Liste erforderlich). –

+0

@Brad Christie IList unterstützt nicht ForEach, Liste tut. –

Antwort

3

Von denen, die Sie erwähnten, ist die erste bevorzugt. Der zweite wird viel mehr tun, indem er in eine Liste konvertiert und nach Typ sucht, nur um am Ende trotzdem eine foreach zu machen.

Es gibt sicherlich andere Möglichkeiten zu iterieren, aber sie hängen von der Sammlung ab.Für IList Implementierungen und Arrays können Sie eine normale for Schleife verwenden und die Elemente mit myitem[i] indizieren.

Aber es gibt keine Gründe, foreach nicht zu verwenden, da es für alle Sammlungen funktioniert und AFAIK immer die optimale Wahl in Bezug auf die Leistung ist. Durch optimale meine ich im Hinblick auf die Komplexität von Algorithmen/big-o

EDIT als Antwort auf Ihre Frage bearbeiten In der Regel sollten Sie die Aufzählung Schema verwenden, die die beste Lesbarkeit bietet (ohne ernsthaft die Leistung zu beeinträchtigen obviosly). In Ihrem Beispiel, wo Sie sehen möchten, ob Ihre Liste Elemente eines bestimmten Typs enthält, würde ich mit der LINQ-Route gehen (collection.OfType...). Es drückt deutlich die Absicht aus und es ist fast möglich, den Text in Englisch zu lesen und die Bedeutung zu erhalten: "In meiner Sammlung, hol dir Elemente vom Typ X und sag mir, wenn es welche gibt."

+1

+1. Siehe auch http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx – TrueWill

+0

Sie müssen nicht "für IList-Implementierungen und -Arrays" sagen, da Arrays IList implementieren . Anscheinend ist 'for' in einigen Fällen marginal schneller als' foreach', aber nicht genug, um einen Unterschied zu machen. – phoog

+0

@phoog Wenn mein Gedächtnis mir gut tut, unterstützen Arrays IList auf eine ziemlich ungewöhnliche Art und aus der Erfahrung, Arrays als ILists zu behandeln, ist mehrere Größenordnungen langsamer. Vielleicht haben sie das Problem behoben ... –

0

Offensichtlich nicht die Sammlung Umwandlung wird schneller sein als es zu konvertieren.

3

Sicher, mit Wende Sammlungen können Sie einen klassischen for-Schleife:

for(int i = 0; i < collection.Count; i++) 
{ 
    collection[i] ... // do something with the item 
} 

Sie können auch direkt Zugriff auf das IEnumerator Objekt (die foreach syntaktischer Zucker für ist):

using(IEnumerator<YourType> e = collection.GetEnumerator()) 
{ 
    while(e.MoveNext()) 
    { 
     // do something with the item 
     e.Current ... 
    } 
} 

Alle Die verschiedenen Ansätze zum Aufzählen einer Sammlung sind in bestimmten Fällen nützlich - es ist jedoch sehr kontextabhängig, welches Muster wo verwendet werden soll.

Zum Beispiel ist die direkte Verwendung des Objekts IEnumerator nützlich, wenn Sie eine feinkörnige Kontrolle darüber haben möchten, wie und wann genau der Iterator inkrementiert und aufgerufen werden soll. Viele LINQ-Operatoren verwenden intern IEnumerator, um ihre Implementierung zu optimieren.

Eine vernünftige Faustregel gilt:, dass, wenn Sie Elemente zu produzieren, um Nebenwirkungen besuchen Sie for oder foreach verwenden sollten, wenn Sie transformieren (Projizieren) eine Sequenz in eine andere sollten Sie LINQ verwenden (Select, Wo, etc ...). Mit LINQ wird das Ergebnis hervorgehoben, während der Mechanismus ausgeblendet wird, während Schleifen den Mechanismus hervorheben.

+0

+1 für die Faustregel. – stackoverflowuser

+0

N.B. Der Typ 'System.Collections.IEnumerator' kann nicht implizit in 'System.IDisposable' konvertiert werden. – Grokodile

+0

@Grokodile: Sie haben Recht. 'IEnumerable' erweitert' IDisposable' nicht, jedoch 'IEnumerable '. – LBushkin

0

Ich würde den ersten Ansatz bevorzugen, weil Sie den zugrunde liegenden Enumerator nicht verlieren, als würden Sie in eine Liste konvertieren. Für die meisten Sammlungen gibt es keinen großen Unterschied, aber wenn es sich um eine große Sammlung handelt oder um eine Berechnung, die Ergebnisse liefert, könnte das wichtig sein.

0

Für einige Arten von Sammlungen (wie Liste (Of T)) Aufzählung über klassische foreach ist viel schneller. Dies liegt daran, dass foreach Konstrukt in C# IEnumerator und IEnumerable nicht direkt verwendet.

Sie ruft die GetEnumerator() -Methode auf und ruft dann MoveNext() und Current on object return auf. Da List die ListEnumerator-Struktur zurückgibt, sind diese Methoden schneller, wenn sie direkt aufgerufen werden, andernfalls über die IEnumerator-Schnittstelle aufrufen.

Verwandte Themen