.NET 4.5Boli pridané dve nové rozhrania kolekcií, IReadOnlyList a IReadOnlyDictionary. Hoci sa tieto rozhrania na prvý pohľad môžu zdať tak všedné, odhaľujú pomerne zložité príbehy o spätnej kompatibilite, interoperabilite a úlohe spolumutability.
IReadOnlyList a IReadOnlyDictionary sú dve rozhrania, ktoré vývojári .NET vždy chceli mať. Okrem poskytovania určitej symetrie (na rozdiel od zapisovateľných rozhraní) by rozhranie len na čítanie malo eliminovať implementáciu metód, ktoré vyhadzujú iba výnimku NotSupportedException a nič nerobia. To všetko nebolo dokončené kvôli časovým obmedzeniam.
Ďalšia príležitosť je tu. NET 2.0. To umožňuje Microsoftu stiahnuť slabo typované kolekcie a nahradiť ich silne typovanými kolegynickými kolekciami. Avšak tím základnej knižnice[1] opäť premeškal príležitosť poskytnúť zoznam len na čítanie, ako napísal Kit George,
Keďže chceme poskytnúť predvolenú implementáciu pre problém, o ktorom hovoríte s Joeom, namiesto rozhrania poskytujeme základnú triedu ReadOnlyCollectionBase. Napriek tomu chápem, prečo sú ľudia neochotní ho používať, pretože nie je silný typ. Ale s príchodom generík máme teraz aj ReadOnlyCollection<T>, takže nielenže získate rovnakú funkcionalitu, ale aj silný typ: skvelé!
Keďže ReadOnlyCollection <T>nie je uzavretá trieda, môžete si v prípade potreby písať vlastnú kolekciu plnou rýchlosťou. Keďže tieto kolekcie, ktoré sme na tento účel vytvorili, sú prispôsobiteľné všeobecným potrebám, neplánujeme zavádzať rozhrania pre tento istý koncept. Krzysztof Cwalina tiež vyjadril svoj názor na túto tému,
Či už to znie prekvapivo alebo nie, IList a IList <T>sú dve rozhrania, ktoré plánujeme použiť pre kolekcie iba na čítanie. Obe majú booleovskú vlastnosť IsReadOnly, ktorá by mala vrátiť true, keď túto vlastnosť implementuje kolekcia iba na čítanie. Dôvod, prečo nechceme pridať čisto čítateľné rozhranie, je ten, že podľa nás pridáva príliš veľa zbytočnej zložitosti do základnej knižnice. Všimnite si, že z hľadiska zložitosti hovoríme o tomto novom rozhraní aj o jeho spotrebiteľoch.
Veríme, že ak dizajnérovi API nezáleží na kontrole vlastnosti IsReadOnly počas behu a na výnimky, ktoré môže vyvolať, potom je v tomto prípade v poriadku použiť rozhranie IList; Ak sú ochotní poskytnúť naozaj čisté vlastné API naraz, mali by v tomto prípade ukázať implementáciu rozhrania IList a publikovať prispôsobené API len na čítanie. To je typické pre kolekcie vystavené z objektového modelu. Aj keď sa vývojári na túto situáciu sťažovali, nové možnosti, ktoré generiká prinášajú, výrazne prevyšujú túto podstatu a problém je v . NET 4 bol predtým väčšinou ignorovaný. Toto rozhodnutie však vyvolalo aj určité reakcie, o ktorých budeme hovoriť neskôr.
S dnu. Do runtime bola pridaná vzrušujúca nová funkcia v .NET 4. V skoršej verzii. .NET, keď sa rozhrania stanú typmi, tieto rozhrania sú príliš obmedzené. Napríklad, aj keď zákazník zdedí od osoby, nie je možné odovzdať objekt typu IEnumerable <Customer>ako parameter funkcii typu IEnumerable<Person>. Pridaním kovariantnej podpory bolo toto obmedzenie čiastočne zrušené.
Hovoríme "čiastočne", pretože v niektorých prípadoch by ľudia mali používať nejaké rozhranie s bohatým API naraz, namiesto použitia IEnumerable rozhrania. Aj keď rozhranie IList nie je kovariantné, rozhranie zoznamu len na čítanie by malo byť. Bohužiaľ, . Tím pre základnú knižnicu .NET sa opäť rozhodol túto chybu neriešiť.
Potom príchod WinRT a návrat COM všetko zmenili. Interoperabilita COM bola kedysi technológiou, ktorú vývojári používali, keď nemali inú možnosť, ale stala sa z nej . Základný kameň .NET programovania. A keďže WinRT sprístupňuje rozhrania IVectorView <T>a IMapView<K, V> rozhrania. .NET je tiež potrebné primerane upraviť.
Jednou zaujímavou vlastnosťou programu WinRT je oznámenie rôznych, no podobných API pre každú vývojovú platformu. Ako už možno viete, všetky názvy metód sú reprezentované camelCased [2], zatiaľ čo vývojári v C++ a .NET vidia názvy metód ako PascalCased [3]. Ďalšou výraznejšou zmenou je automatické mapovanie medzi rozhraniami C++ a .NET. Preto. Vývojári .NET nemusia riešiť menný priestor Windows.Foundation.Collections, stačí pokračovať v používaní menného priestoru System.Collections.Generic. Rozhrania IVectorView <T>a IMapView<K, V> budú počas behu prevedené na rozhrania IReadOnlyList <T>a IReadOnlyDictionary<TKey, TValue> rozhrania.
Stojí za zmienku, že tieto názvy rozhraní v C++/WinRT sú do istej miery presnejšie. Tieto rozhrania sa používajú na reprezentáciu niektorých pohľadov na kolekciu, ale rozhranie nezaručuje, že samotná kolekcia je nemenná. Dokonca aj medzi tými, ktorí majú skúsenosti. Bežnou chybou medzi .NET vývojármi je predpokladať, že typ ReadOnlyCollection je kópiou nemennej kolekcie, ale v skutočnosti ide len o obal pre aktívnu kolekciu (viac informácií o read-only, frozen a immutable kolekciách nájdete v príspevku Andrewa Arnotta s rovnakým názvom).
Hoci rozhranie IList <T>má všetky rovnaké členy ako rozhranie IReadOnlyList <T>a všetky zoznamy typu IList <T>môžu byť reprezentované len na čítanie, IList <T>nepreberá z IReadOnlyList<T>, čo môže byť zaujímavé na zistenie. Immo Landwerth vysvetlil,
Dôvod, prečo to funguje, je ten, že tieto rozhrania len na čítanie sú čisto podmnožinami rozhranií na čítanie a zápis, čo sa zdá byť rozumným predpokladom. Bohužiaľ, tento predpoklad nezodpovedá realite, pretože každá metóda na každom rozhraní na úrovni metadát má svoj vlastný slot (čo umožňuje fungovanie explicitných implementácií rozhraní). Inými slovami, jediná šanca zaviesť rozhranie iba na čítanie ako nejakú základnú triedu premennej triedy je vrátiť sa k . NET 2.0, teda keď boli pôvodne koncipované. Keď je úplne rozvinutý, jedinou zmenou, ktorú môže urobiť, je pridať kovariantné a/alebo invertorové markery (reprezentované ako "in" a "out" vo VB a C#).
Na otázku, prečo neexistuje rozhranie IReadOnlyCollection<T>, Immo odpovedal,
Zvažovali sme tento dizajn, ale mali sme pocit, že pridanie typu, ktorý poskytuje iba atribút Count, by základnej knižnici veľa nepridalo. V tíme základnej knižnice veríme, že ak API začína na mínus 1000, ani poskytnutie nejakej hodnoty nestačí na to, aby sa oplatilo pridať. Dôvod na pridanie nových API zahŕňa aj náklady, napríklad vývojári budú mať na výber viac konceptov. Najprv sme si mysleli, že pridanie tohto typu pomôže kódu lepšie fungovať v určitých situáciách, kde chcete len získať počet a potom s ním urobiť niečo zaujímavé. Napríklad hromadné pridávanie do existujúcej kolekcie. V týchto prípadoch sme však povzbudzovali ľudí, aby používali iba rozhranie IEnumerable<T>, a <T>v špeciálnom prípade mať inštanciu, ktorá implementuje ICollection rozhranie. Keďže všetky naše vstavané typy kolekcií implementovali toto rozhranie, v týchto najbežnejších scenároch nedošlo k žiadnemu nárastu výkonu. Mimochodom, <T>rozširujúca metóda Count() pre IEnumerable to tiež dokáže. Tieto nové rozhrania sú dostupné pre . NET 4.5 a . NET for Windows 8。
Poznámky k prekladu
[1] Knižnica základnej triedy, skrátene BCL. Pre viac informácií o knižnici základných tried sa prosím zapojte do MSDN.
[2] ťava puzdro, nomenklatúra hrbov, známa aj ako dolný ťaví prípad. Formát je taký, že prvé slovo začína malým písmenom; Prvé písmeno druhého slova sa píše s veľkým písmenom, napríklad: firstName, LastName.
[3] PascalCased, Pascalova nomenklatúra, známa aj ako prípad hornej ťavy. Formát je taký, že prvé písmeno každého slova sa píše s veľkým písmenom, napríklad: Meno, Priezvisko, CamelCase. |