.NET 4.5Zwei neue Sammlungsschnittstellen, IReadOnlyList und IReadOnlyDictionary, wurden hinzugefügt. Obwohl diese Schnittstellen auf den ersten Blick so alltäglich erscheinen mögen, offenbaren sie ziemlich komplexe Geschichten über Abwärtskompatibilität, Interoperabilität und die Rolle der Ko-Mutierbarkeit.
IReadOnlyList und IReadOnlyDictionary sind zwei Schnittstellen, die .NET-Entwickler schon immer haben wollten. Neben einer gewissen Symmetrie (im Gegensatz zu beschreibbaren Schnittstellen) sollte eine schreibgeschützte Schnittstelle die Implementierung von Methoden eliminieren, die nur eine NotSupportedException-Ausnahme auslösen und nichts tun. All dies wurde aus Zeitgründen nicht abgeschlossen.
Die nächste Chance ist gekommen. NET 2.0. Dies ermöglicht es Microsoft, schwach typisierte Sammlungen zurückzuziehen und durch stark typisierte Peer-Sammlungen zu ersetzen. Allerdings verpasste das Team der Basisbibliothek[1] erneut die Gelegenheit, eine Nur-lese-Liste bereitzustellen, wie Kit George schrieb:
Da wir beabsichtigen, eine Standardimplementierung für das von Ihnen angesprochene Problem mit Joe bereitzustellen, anstatt eine Schnittstelle bereitzustellen, stellen wir die Basisklasse ReadOnlyCollectionBase bereit. Ich kann jedoch verstehen, warum viele zögern, es zu verwenden, weil es kein starker Typ ist. Aber mit der Einführung der Generika gibt es jetzt auch ReadOnlyCollection<T>, sodass Sie nicht nur die gleiche Funktionalität, sondern auch einen starken Typ erhalten: großartig!
Da ReadOnlyCollection <T>keine versiegelte Klasse ist, kannst du bei Bedarf deine eigene Sammlung mit voller Geschwindigkeit schreiben. Da diese Sammlungen, die wir dafür erstellt haben, an allgemeine Bedürfnisse angepasst werden können, planen wir nicht, Schnittstellen für dieses Konzept einzuführen. Krzysztof Cwalina äußerte ebenfalls seine Meinung zu diesem Thema,
Ob das nun überraschend klingt oder nicht, IList und IList <T>sind die beiden Schnittstellen, die wir für Read-only-Sammlungen verwenden wollen. Beide besitzen die boolesche Eigenschaft IsReadOnly, die true zurückgeben sollte, wenn eine Read-only-Sammlung diese Eigenschaft implementiert. Der Grund, warum wir keine reine schreibgeschützte Oberfläche hinzufügen wollen, ist, dass wir das Gefühl haben, dass sie der Basisbibliothek zu viel unnötige Komplexität verleiht. Beachten Sie, dass wir uns in Bezug auf die Komplexität sowohl auf diese neue Schnittstelle als auch auf ihre Nutzer beziehen.
Wir glauben, dass es in diesem Fall in Ordnung ist, die IList-Oberfläche zu verwenden, wenn der API-Designer nicht darauf achtet, die Eigenschaft IsReadOnly zur Laufzeit und die möglichen Ausnahmen zu überprüfen; Wenn sie bereit sind, eine wirklich saubere, maßgeschneiderte API auf einmal bereitzustellen, sollten sie in diesem Fall die Implementierung der IList-Schnittstelle zeigen und eine maßgeschneiderte, schreibgeschützte API veröffentlichen. Letzteres ist typisch für Sammlungen, die aus dem Objektmodell freigegeben werden. Obwohl sich Entwickler über diese Situation beschwert haben, überwiegen die neuen Möglichkeiten, die Generika bieten, diesen Kern bei Weitem, und das Problem liegt in . NET 4 wurde zuvor weitgehend ignoriert. Diese Entscheidung löste jedoch auch einige Reaktionen aus, auf die wir später eingehen werden.
Mit dem In. Eine spannende neue Funktion in .NET 4 wurde zur Laufzeit hinzugefügt. In einer früheren Version. .NET, wenn Schnittstellen zu Typen werden, sind diese Schnittstellen übermäßig eingeschränkt. Zum Beispiel ist es selbst wenn Customer von Person erbt, nicht möglich, ein Objekt vom Typ IEnumerable <Customer>als Parameter an eine Funktion des Typs IEnumerable zu übergeben<Person>. Mit der Hinzufügung der kovarianten Unterstützung wurde diese Einschränkung teilweise aufgehoben.
Wir sagen "teilweise", weil man in manchen Fällen eine Schnittstelle mit einer reichen API gleichzeitig nutzen sollte, anstatt eine IEnumerable Schnittstelle zu verwenden. Selbst wenn die IList-Schnittstelle nicht kovariant ist, sollte eine schreibgeschützte Listenoberfläche es sein. Leider gilt . Das .NET-Basisbibliotheksteam hat erneut beschlossen, dieses Versäumnis nicht anzugehen.
Dann änderten die Einführung von WinRT und das Comeback von COM alles. COM-Interoperabilität war einst eine Technologie, die Entwickler nutzten, wenn sie keine andere Wahl hatten, aber sie ist inzwischen zu einem . Das Grundpfeiler der .NET-Programmierung. Und da WinRT die Schnittstellen IVectorView <T>und IMapView<K, V> offenlegt. .NET muss ebenfalls entsprechend angepasst werden.
Ein interessantes Merkmal des WinRT-Programms ist die Ankündigung unterschiedlicher, aber ähnlicher APIs für jede Entwicklungsplattform. Wie Sie vielleicht bereits wissen, werden alle Methodennamen durch camelCased [2] dargestellt, während C++- und .NET-Entwickler Methodennamen als PascalCased [3] betrachten. Eine weitere, drastischere Änderung ist die automatische Zuordnung zwischen den C++- und .NET-Schnittstellen. Deshalb. .NET-Entwickler müssen sich nicht mit dem Windows.Foundation.Collections-Namensraum auseinandersetzen, sondern weiterhin den System.Collections.Generic Namensraum verwenden. Die Schnittstellen IVectorView <T>und IMapView<K, V> werden zur Laufzeit in IReadOnlyList-Schnittstellen <T>bzw. IReadOnlyDictionary<TKey, TValue> umgewandelt.
Es ist erwähnenswert, dass diese Schnittstellennamen in C++/WinRT bis zu einem gewissen Grad genauer sind. Diese Schnittstellen werden verwendet, um einige Ansichten einer Sammlung darzustellen, aber die Schnittstelle stellt nicht sicher, dass die Sammlung selbst unveränderlich ist. Sogar unter denen mit Erfahrung. Ein häufiger Fehler unter .NET-Entwicklern ist anzunehmen, dass der Typ ReadOnlyCollection eine Kopie einer unveränderlichen Sammlung ist, tatsächlich aber nur ein Wrapper für eine aktive Sammlung ist (siehe Andrew Arnotts Beitrag gleichen Namens für weitere Informationen zu schreibgeschützten, eingefrorenen und unveränderlichen Sammlungen).
Obwohl die <T>IList-Schnittstelle alle gleichen Mitglieder wie die IReadOnlyList-Schnittstelle hat <T>und alle IList-Typen <T>als schreibgeschützte Listen dargestellt werden können, <T>erbt IList nicht von IReadOnlyList<T>, was interessant sein könnte. erklärte Immo Landwerth,
Der Grund, warum es funktioniert, ist, dass diese schreibgeschützten Schnittstellen reine Teilmengen von Lese-Schreib-Schnittstellen sind, was eine vernünftige Annahme erscheint. Leider entspricht diese Annahme nicht der Realität, da jede Methode auf jeder Schnittstelle auf Metadatenebene ihren eigenen Slot hat (was explizite Schnittstellenimplementierungen ermöglicht). Oder mit anderen Worten: Die einzige Möglichkeit, eine schreibgeschützte Schnittstelle als eine variable Klassenbasisklasse einzuführen, besteht darin, auf zurückzufallen. NET 2.0, also als sie ursprünglich konzipiert wurden. Sobald er vollständig ausgerollt ist, kann nur noch eine Änderung vorgenommen werden, kovariante und/oder Wechselrichtermarker hinzuzufügen (dargestellt als "rein" und "raus" in VB und C#).
Auf die Frage, warum es keine IReadOnlyCollection-Oberfläche gibt<T>, antwortete Immo:
Wir haben dieses Design in Betracht gezogen, aber wir waren der Meinung, dass das Hinzufügen eines Typs, der nur das Count-Attribut bereitstellt, der Basisbibliothek nicht viel Mehrwert bringen würde. Im Basisbibliotheksteam glauben wir, dass wenn eine API bei minus 1000 startet, selbst ein gewisser Wert nicht ausreicht, um eine Hinzufügung zu rechtfertigen. Die Begründung für das Hinzufügen neuer APIs beinhaltet auch Kosten, zum Beispiel haben Entwickler mehr Konzepte zur Auswahl. Zuerst dachten wir, dass das Hinzufügen dieses Typs den Code in bestimmten Situationen verbessern würde, in denen man einfach nur eine Zählung machen und dann etwas Interessantes damit machen möchte. Zum Beispiel eine große Erweiterung einer bestehenden Sammlung hinzufügen. In diesen Szenarien haben wir jedoch dazu ermutigt, nur die IEtallable-Schnittstelle zu verwenden<T>, und <T>zwar im Spezialfall, dass eine Instanz die ICollection-Schnittstelle implementiert. Da alle unsere integrierten Sammlungstypen diese Schnittstelle implementiert haben, gab es in diesen häufigsten Szenarien keinen Leistungsgewinn. Übrigens <T>kann die Erweiterungsmethode Count() für IEnumerable das ebenfalls tun. Diese neuen Schnittstellen sind verfügbar für . NET 4,5 und . NET for Windows 8。
Übersetzungsanmerkungen
[1] Base Class Library, abgekürzt BCL. Für weitere Informationen über die Basisbibliothek nehmen Sie bitte an MSDN teil.
[2] Kamelgehäuse, Buckel-Nomenklatur, auch bekannt als unteres Kamelgehäuse. Das Format besteht darin, dass das erste Wort mit einem Kleinbuchstaben beginnt; Der erste Buchstabe des zweiten Wortes wird großgeschrieben, zum Beispiel: firstName, afterName.
[3] Pascal Mit Gehäuse, Pascal-Nomenklatur, auch bekannt als Oberkamel-Gehäuse. Das Format besteht darin, dass der erste Buchstabe jedes Wortes großgeschrieben wird, zum Beispiel: FirstName, AfterName, CamelCase. |