Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dieser Inhalt wird mit Genehmigung von Pearson Education, Inc. aus Framework Design Guidelines: Konventionen, Idiome und Muster für wiederverwendbare .NET-Bibliotheken, 2. Auflage nachgedruckt. Diese Ausgabe wurde 2008 veröffentlicht, und das Buch wurde seitdem in der dritten Ausgabe vollständig überarbeitet. Einige der Informationen auf dieser Seite sind möglicherweise veraltet.
Jeder Typ, der speziell zum Bearbeiten einer Gruppe von Objekten entwickelt wurde, die ein gemeinsames Merkmal aufweisen, kann als Sammlung betrachtet werden. Es ist fast immer geeignet, solche Typen zu implementieren IEnumerable oder IEnumerable<T>, daher sollten in diesem Abschnitt nur Typen implementiert werden, die eine oder beide dieser Schnittstellen als Auflistungen implementieren.
❌ Verwenden Sie keine schwach typierten Auflistungen in öffentlichen APIs.
Der Typ aller Rückgabewerte und Parameter, die Auflistungselemente darstellen, sollte der genaue Elementtyp sein, nicht einer seiner Basistypen (dies gilt nur für öffentliche Mitglieder der Auflistung).
❌ Verwenden Sie ArrayList oder List<T> nicht in öffentlichen APIs.
Diese Typen sind Datenstrukturen, die in der internen Implementierung verwendet werden sollen, nicht in öffentlichen APIs.
List<T>
ist auf Leistung und Energieeffizienz optimiert, jedoch auf Kosten der Klarheit der APIs und der Flexibilität. Wenn Sie beispielsweise List<T>
zurückgeben, werden Sie niemals in der Lage sein, Benachrichtigungen zu empfangen, wenn der Clientcode die Sammlung modifiziert. Darüber hinaus legt List<T>
viele Mitglieder offen, wie zum Beispiel BinarySearch, die in vielen Szenarien nicht nützlich oder anwendbar sind. In den folgenden beiden Abschnitten werden Typen (Abstraktionen) beschrieben, die speziell für die Verwendung in öffentlichen APIs entwickelt wurden.
❌ Verwenden Sie Hashtable
oder Dictionary<TKey,TValue>
nicht in öffentlichen APIs.
Diese Typen sind Datenstrukturen, die in der internen Implementierung verwendet werden sollen. Öffentliche APIs sollten IDictionary, IDictionary <TKey, TValue>
oder einen benutzerdefinierten Typ verwenden, der eine oder beide Schnittstellen implementiert.
❌ VERWENDEN SIE IEnumerator<T> NICHT, IEnumerator oder einen anderen Typ, der eine der Schnittstellen implementiert, außer als Rückgabewert einer GetEnumerator
Methode.
Typen, die aus anderen Methoden als GetEnumerator
Enumeratoren zurückgeben, können nicht mit der foreach
-Anweisung verwendet werden.
❌ Implementieren Sie nicht sowohl IEnumerator<T>
als auch IEnumerable<T>
auf demselben Typ. Gleiches gilt für die nichtgenerischen Schnittstellen IEnumerator
und IEnumerable
.
Sammlungsparameter
✔️ Verwenden Sie den am wenigsten spezialisierten Typ als Parametertyp. Die meisten Mitglieder, die Sammlungen als Parameter verwenden, verwenden die IEnumerable<T>
Schnittstelle.
❌ VERMEIDEN Sie die Verwendung ICollection<T> oder ICollection als Parameter nur für den Zugriff auf die Count
Eigenschaft.
Erwägen Sie stattdessen die Verwendung von IEnumerable<T>
oder IEnumerable
und überprüfen Sie dynamisch, ob das Objekt ICollection<T>
oder ICollection
implementiert.
Sammlungseigenschaften und Rückgabewerte
❌ Stellen Sie keine konfigurierbaren Collections-Eigenschaften bereit.
Benutzer können den Inhalt der Sammlung ersetzen, indem Sie zuerst die Sammlung löschen und dann den neuen Inhalt hinzufügen. Wenn das Ersetzen der gesamten Auflistung ein häufiges Szenario ist, sollten Sie die AddRange
Methode für die Auflistung bereitstellen.
Verwenden Sie Collection<T>
oder eine Unterklasse von Collection<T>
für Eigenschaften oder Rückgabewerte, die Lese-/Schreibsammlungen darstellen.
Wenn Collection<T>
einige Anforderungen nicht erfüllt (z.B. darf die Sammlung nicht IList implementieren), verwenden Sie eine benutzerdefinierte Sammlung, indem Sie IEnumerable<T>
, ICollection<T>
oder IList<T> verwenden.
✔️ Verwenden Sie ReadOnlyCollection<T>, eine Unterklasse von ReadOnlyCollection<T>
oder in seltenen Fällen IEnumerable<T>
für Eigenschaften oder Rückgabewerte, die schreibgeschützte Auflistungen darstellen.
Im Allgemeinen bevorzugen ReadOnlyCollection<T>
. Wenn sie eine bestimmte Anforderung nicht erfüllt (z. B. darf die Sammlung nicht IList
implementieren), verwenden Sie eine benutzerdefinierte Sammlung, indem Sie IEnumerable<T>
, ICollection<T>
oder IList<T>
implementieren. Wenn Sie eine benutzerdefinierte schreibgeschützte Sammlung implementieren, verwenden Sie ICollection<T>.IsReadOnly
für die Rückgabe von true
.
In Fällen, in denen Sie sicher sind, dass das einzige Szenario, das Sie jemals unterstützen möchten, eine vorwärtsgerichtete Iteration ist, können Sie einfach verwenden IEnumerable<T>
.
✔️ Erwägen Sie die Verwendung von Unterklassen generischer Basissammlungen anstelle davon, die Sammlungen direkt zu verwenden.
Dies ermöglicht einen besseren Namen und das Hinzufügen von Hilfselementen, die nicht in den Basissammlungstypen vorhanden sind. Dies gilt insbesondere für apIs auf hoher Ebene.
✔️ ERWÄGEN Sie, eine Unterklasse von Collection<T>
oder ReadOnlyCollection<T>
aus sehr häufig verwendeten Methoden und Eigenschaften zurückzugeben.
Auf diese Weise können Sie Hilfsmethoden hinzufügen oder die Sammlungsimplementierung in Zukunft ändern.
✔️ ERWÄGEN SIE die Verwendung einer Schlüsselauflistung, wenn die in der Sammlung gespeicherten Elemente eindeutige Schlüssel (Namen, IDs usw.) aufweisen. Indizierte Sammlungen sind Sammlungen, die sowohl mit einer ganzen Zahl als auch mit einem Schlüssel indiziert werden können und in der Regel durch Ableitung von KeyedCollection<TKey,TItem>
implementiert werden.
Schlüsselsammlungen weisen in der Regel größere Speicherabdrücke auf und sollten nicht verwendet werden, wenn der Arbeitsspeicheraufwand die Vorteile der Schlüssel überwiegt.
❌ GEBEN SIE KEINE Nullwerte aus Sammlungs-Eigenschaften oder aus Methoden zurück, die Sammlungen zurückgeben. Geben Sie stattdessen eine leere Auflistung oder ein leeres Array zurück.
Die allgemeine Regel besteht darin, dass Null- und leere Auflistungen (0 Element) oder Arrays gleich behandelt werden sollen.
Momentaufnahmen im Vergleich zu Livesammlungen
Auflistungen, die einen Zustand zu einem bestimmten Zeitpunkt darstellen, werden als Snapshotsammlungen bezeichnet. Beispielsweise wäre eine Auflistung, die Zeilen enthält, die aus einer Datenbankabfrage zurückgegeben werden, eine Momentaufnahme. Sammlungen, die immer den aktuellen Zustand darstellen, werden als Livesammlungen bezeichnet. Beispielsweise handelt es sich bei einer Sammlung von ComboBox
Elementen um eine dynamische Sammlung.
❌ NICHT Schnappschusssammlungen von Eigenschaften zurückgeben. Eigenschaften sollten Livesammlungen zurückgeben.
Eigenschafts-Zugriffs-Funktionen sollten sehr ressourcenschonende Operationen sein. Um eine Momentaufnahme zurückzugeben, muss eine Kopie einer internen Sammlung durch einen O(n)-Prozess erstellt werden.
✔️ Verwenden Sie entweder eine Momentaufnahme-Sammlung oder eine Live-Sammlung IEnumerable<T>
(oder ihren Untertyp), um Sammlungen darzustellen, die flüchtig sind (d. h., die sich ändern können, ohne die Sammlung explizit zu ändern).
Im Allgemeinen sind alle Sammlungen, die eine freigegebene Ressource darstellen (z. B. Dateien in einem Verzeichnis), veränderlich. Solche Sammlungen sind sehr schwierig oder unmöglich als Live-Sammlungen zu implementieren, es sei denn, die Implementierung besteht einfach aus einem Vorwärts-Enumerator.
Auswählen zwischen Arrays und Sammlungen
✔️ DO bevorzugt Sammlungen anstatt Arrays.
Sammlungen bieten mehr Kontrolle über Inhalte, können sich im Laufe der Zeit weiterentwickeln und besser nutzbar sein. Darüber hinaus wird davon abgeraten, Arrays für Nur-Lesen-Szenarien zu verwenden, da die Kosten für das Klonen des Arrays unerschwinglich sind. Benutzerfreundlichkeitsstudien haben gezeigt, dass sich einige Entwickler mit sammlungsbasierten APIs wohler fühlen.
Wenn Sie jedoch APIs auf niedriger Ebene entwickeln, ist es möglicherweise besser, Arrays für Lese-/Schreibszenarien zu verwenden. Arrays haben einen kleineren Speicherbedarf, wodurch der Arbeitssatz reduziert wird, und der Zugriff auf Elemente in einem Array ist schneller, da sie durch die Laufzeit optimiert wird.
✔️ ERWÄGEN SIE die Verwendung von Arrays in APIs auf niedriger Ebene, um den Speicherverbrauch zu minimieren und die Leistung zu maximieren.
✔️ Verwenden Sie Bytearrays anstelle von Bytesammlungen.
❌ VERWENDEN SIE KEINE Arrays für Eigenschaften, wenn die Eigenschaft jedes Mal ein neues Array (z. B. eine Kopie eines internen Arrays) zurückgeben muss, wenn der Eigenschafts-Getter aufgerufen wird.
Implementieren von benutzerdefinierten Sammlungen
✔️ ERWÄGEN SIE, von Collection<T>
, ReadOnlyCollection<T>
oder KeyedCollection<TKey,TItem>
zu erben, wenn Sie neue Sammlungen entwerfen.
✔️ Implementieren sie IEnumerable<T>
beim Entwerfen neuer Sammlungen. Erwägen Sie die Implementierung von ICollection<T>
oder sogar IList<T>
dort, wo es sinnvoll ist.
Folgen Sie bei der Implementierung einer solchen benutzerdefinierten Sammlung dem API-Muster, das von Collection<T>
und ReadOnlyCollection<T>
so genau wie möglich eingerichtet wurde. Mit anderen Worten, implementieren Sie die gleichen Member explizit, benennen Sie die Parameter so, wie diese beiden Auflistungen ihre Elemente benennen, und so weiter.
✔️ ERWÄGEN SIE die Implementierung nichtgenerischer Sammlungsschnittstellen (IList
und ICollection
) wenn die Sammlung häufig an APIs übergeben wird, die diese Schnittstellen als Eingabe verwenden.
❌ VERMEIDEN Sie die Implementierung von Sammlungsschnittstellen für Typen mit komplexen APIs, die nicht mit dem Konzept einer Auflistung zusammenhängen.
❌ Vererben Sie NICHT von nicht-generischen Basissammlungen wie CollectionBase
. Verwenden Sie Collection<T>
stattdessen , ReadOnlyCollection<T>
und KeyedCollection<TKey,TItem>
.
Benennen benutzerdefinierter Sammlungen
Sammlungen (Typen, die IEnumerable
implementieren) werden hauptsächlich aus zwei Gründen erstellt: (1) zum Erstellen einer neuen Datenstruktur mit strukturspezifischen Vorgängen und häufig unterschiedlichen Leistungsmerkmalen als bei vorhandenen Datenstrukturen (z. B. List<T>, LinkedList<T>, Stack<T>) und (2) zum Erstellen einer speziellen Sammlung zum Halten einer bestimmten Gruppe von Elementen (z. B. StringCollection). Datenstrukturen werden am häufigsten in der internen Implementierung von Anwendungen und Bibliotheken verwendet. Spezialisierte Auflistungen werden hauptsächlich in APIs (als Eigenschafts- und Parametertypen) verfügbar gemacht.
✔️ Verwenden Sie das Suffix "Dictionary" in Namen von Abstraktionen, die IDictionary
oder IDictionary<TKey,TValue>
implementieren.
✔️ Verwenden Sie das Suffix "Collection" in Namen von Typen, die IEnumerable
oder eines seiner Nachkommen implementieren und eine Liste von Elementen darstellen.
✔️ Verwenden Sie den entsprechenden Datenstrukturnamen für benutzerdefinierte Datenstrukturen.
❌ VERMEIDEN Sie die Verwendung von Suffixen, die eine bestimmte Implementierung impliziert, z. B. "LinkedList" oder "Hashtable", in Namen von Sammlungsabstraktionen.
✔️ ERWÄGEN Sie, Auflistungsnamen mit dem Namen des Elementtyps zu versehen. Beispielsweise sollte eine Sammlung, in der Elemente vom Typ Address
gespeichert werden (implementieren IEnumerable<Address>
) benannt AddressCollection
werden. Wenn der Elementtyp eine Schnittstelle ist, kann das Präfix "I" des Elementtyps weggelassen werden. So kann eine Sammlung von IDisposable Elementen DisposableCollection
genannt werden.
✔️ ERWÄGEN SIE die Verwendung des Präfixes "ReadOnly" in Namen schreibgeschützter Auflistungen, wenn eine entsprechende schreibbare Auflistung hinzugefügt oder bereits im Framework vorhanden ist.
Beispielsweise sollte eine schreibgeschützte Auflistung von Zeichenfolgen ReadOnlyStringCollection
genannt werden.
© Teile 2005, 2009 Microsoft Corporation. Alle Rechte vorbehalten.
Nachdruck mit Genehmigung von Pearson Education, Inc. aus Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2. Auflage von Krzysztof Cwalina und Brad Abrams, veröffentlicht am 22. Okt 2008 von Addison-Wesley Professional als Teil der Microsoft Windows Development Series.