Ein Mitarbeiter hat mich heute gefragt, wie ich einer Sammlung einen Bereich hinzufügen kann. Er hat eine Klasse, die von erbt Collection<T>
. Es gibt eine Get-Only-Eigenschaft dieses Typs, die bereits einige Elemente enthält. Er möchte die Objekte in einer anderen Sammlung zur Eigenschaftssammlung hinzufügen. Wie kann er das C # 3-freundlich machen? (Beachten Sie die Einschränkung bezüglich der get-only-Eigenschaft, die Lösungen wie Union und Neuzuweisung verhindert.)
Sicher, ein Foreach mit Eigentum. Hinzufügen wird funktionieren. Ein List<T>
AddRange im Stil wäre jedoch weitaus eleganter.
Es ist einfach genug, eine Erweiterungsmethode zu schreiben:
public static class CollectionHelpers
{
public static void AddRange<T>(this ICollection<T> destination,
IEnumerable<T> source)
{
foreach (T item in source)
{
destination.Add(item);
}
}
}
Aber ich habe das Gefühl, das Rad neu zu erfinden. Ich habe nichts Ähnliches in System.Linq
oder Morelinq gefunden .
Schlechtes Design? Einfach Add anrufen? Vermissen Sie das Offensichtliche?
quelle
ICollection<T>
scheint keineAdd
Methode zu haben . msdn.microsoft.com/en-us/library/… Hat jedochCollection<T>
eine.Add(T item)
? Scheint ein halbherziger Ansatz zu sein, der die Möglichkeit bietet, ein einzelnes Element hinzuzufügen und dann zu erwarten, dass alle Anrufer iterieren, um mehr als ein Element gleichzeitig hinzuzufügen. Ihre Aussage ist sicherlich richtig,IEnumerable<T>
aber ich warICollections
mehr als einmal frustriert . Ich bin nicht anderer Meinung als Sie, nur entlüften.Antworten:
Nein, das scheint völlig vernünftig. Es gibt eine
List<T>.
AddRange () -Methode, die im Grunde genau dies tut, aber erfordert, dass Ihre Sammlung konkret istList<T>
.quelle
Versuchen Sie, in der Erweiterungsmethode in List umzuwandeln, bevor Sie die Schleife ausführen. Auf diese Weise können Sie die Leistung von List.AddRange nutzen.
quelle
as
Bediener wird niemals werfen. Wenndestination
nicht umgewandelt werden kann,list
ist null und derelse
Block wird ausgeführt.if (destination is List<T> list)
Da ,
.NET4.5
wenn Sie Einzeiler möchten Sie verwenden könnenSystem.Collections.Generic
FürJeden.oder noch kürzer als
In Bezug auf die Leistung ist es das gleiche wie für jede Schleife (syntaktischer Zucker).
Versuchen Sie auch nicht , es wie zuzuweisen
Ursache
ForEach
ist nichtig.Bearbeiten: Aus Kommentaren kopiert , Liperts Meinung zu ForEach
quelle
ForEach
scheint nur definiert zu seinList<T>
, nichtCollection
?Denken Sie daran, dass jeder
Add
die Kapazität der Sammlung überprüft und bei Bedarf die Größe ändert (langsamer). MitAddRange
wird die Sammlung die Kapazität eingestellt und dann die Elemente hinzugefügt (schneller). Diese Erweiterungsmethode ist extrem langsam, funktioniert aber.quelle
Hier ist eine etwas fortgeschrittenere / produktionsbereite Version:
quelle
Die C5 generische Sammlungen Bibliothek Klassen alle unterstützen
AddRange
Methode. C5 verfügt über eine viel robustere Schnittstelle, die tatsächlich alle Funktionen der zugrunde liegenden Implementierungen verfügbar macht und mit den SchnittstellenSystem.Collections.Generic
ICollection
und kompatibel ist. DiesIList
bedeutet, dassC5
die Sammlungen leicht als zugrunde liegende Implementierung ersetzt werden können.quelle
Sie können Ihren IEnumerable-Bereich zu einer Liste hinzufügen und dann die ICollection = auf die Liste setzen.
quelle
Oder Sie können einfach eine ICollection-Erweiterung wie folgt erstellen:
Die Verwendung wäre wie die Verwendung in einer Liste:
quelle