Ten artykuł jest lustrzanym artykułem tłumaczenia maszynowego, kliknij tutaj, aby przejść do oryginalnego artykułu.

Widok: 19672|Odpowiedź: 1

[Źródło] . .NET Historia interfejsu kolekcji tylko do odczytu

[Skopiuj link]
Opublikowano 05.02.2018 14:28:10 | | |
.NET 4.5Dodano dwa nowe interfejsy kolekcji: IReadOnlyList i IReadOnlyDictionary. Chociaż te interfejsy mogą wydawać się tak zwyczajne, ujawniają dość złożone historie dotyczące kompatybilności wstecznej, interoperacyjności i roli współmutowalności.

IReadOnlyList i IReadOnlyDictionary to dwa interfejsy, które deweloperzy .NET zawsze chcieli mieć. Oprócz zapewnienia pewnej symetrii (w przeciwieństwie do zapisywalnych interfejsów), interfejs tylko do odczytu powinien wyeliminować implementację metod, które wyrzucają tylko wyjątek NotSupportedException i nic nie robią. Wszystko to nie zostało ukończone z powodu ograniczeń czasowych.

Następna okazja jest bliska. NET 2.0. Pozwala to Microsoftowi wycofać kolekcje słabo typowane i zastąpić je silnie typowanymi kolekcjami rówieśniczymi. Jednak zespół biblioteki bazowej[1] ponownie przegapił okazję, by udostępnić listę tylko do czytania, jak napisał Kit George,

Ponieważ zamierzamy dostarczyć domyślną implementację dla problemu, o którym mówisz z Joe, zamiast podawać interfejs, udostępniamy klasę bazową ReadOnlyCollectionBase. Jednak rozumiem, dlaczego ludzie niechętnie go używają, bo nie jest to mocny typ. Ale wraz z wprowadzeniem generyków mamy teraz także ReadOnlyCollection<T>, dzięki czemu nie tylko masz tę samą funkcjonalność, ale też mocny typ: świetnie!

Ponieważ ReadOnlyCollection <T>nie jest klasą zamkniętą, możesz pisać własną kolekcję z pełną prędkością, jeśli zajdzie taka potrzeba. Ponieważ kolekcje, które stworzyliśmy w tym celu, są dostosowane do ogólnych potrzeb, nie planujemy wprowadzać interfejsów dla tej samej koncepcji.

Krzysztof Cwalina również wyraził swoje zdanie na ten temat,

Niezależnie od tego, czy brzmi to zaskakująco, czy nie, IList i IList <T>to dwa interfejsy, których zamierzamy używać dla kolekcji tylko do odczytu. Obie mają właściwość boole'a IsReadOnly, która powinna zwracać true, gdy kolekcja tylko do odczytu implementuje tę właściwość. Powodem, dla którego nie chcemy dodawać interfejsu tylko do odczytu, jest to, że uważamy, iż dodaje on zbyt dużo niepotrzebnej złożoności do bazowej biblioteki. Należy zauważyć, że w kategoriach złożoności odnosimy się zarówno do tego nowego interfejsu, jak i jego odbiorców.

Uważamy, że jeśli projektant API nie zwraca uwagi na sprawdzanie właściwości IsReadOnly w czasie działania i wyjątków, które może wywołać, to w tym przypadku można użyć interfejsu IList; Jeśli są gotowi dostarczyć naprawdę czyste, niestandardowe API za jednym zamachem, to w tym przypadku powinni pokazać implementację interfejsu IList i opublikować dopasowane API tylko do odczytu. To drugie jest typowe dla kolekcji wystawionych na model obiektowy.

Chociaż deweloperzy narzekali na tę sytuację, nowe możliwości oferowane przez generyki znacznie przewyższają ten sedno i problem leży w. NET 4 był wcześniej w dużej mierze ignorowany. Jednak ta decyzja wywołała także pewne reakcje, o których porozmawiamy później.

Z wejściem. Do środowiska uruchomieniowego dodano ekscytującą nową funkcję w .NET 4. W wcześniejszej wersji. .NET, gdy interfejsy stają się typami, te interfejsy są zbyt ograniczone. Na przykład, nawet jeśli klient dziedziczy od osoby, nie jest możliwe przekazanie obiektu typu IEnumerable <Customer>jako parametru funkcji typu IEnumerable<Person>. Dzięki dodaniu wsparcia kowariantnego ograniczenie to zostało częściowo zniesione.

Mówimy "częściowo", ponieważ w niektórych przypadkach ludzie powinni używać interfejsu z bogatym API naraz, zamiast korzystać z interfejsu IEnumerable. Nawet jeśli interfejs IList nie jest kowariantny, interfejs listy tylko do odczytu powinien być. Niestety, . Zespół bibliotek bazowych .NET ponownie zdecydował się nie poruszać tego niedopatrzenia.

Potem wprowadzenie WinRT i powrót COM zmieniły wszystko. Interoperacyjność COM była kiedyś technologią, z której deweloperzy korzystali, gdy nie mieli innego wyboru, ale stała się ona . Kamień węgielny programowania .NET. A ponieważ WinRT udostępnia interfejsy IVectorView <T>i IMapView<K, V> więc. .NET również musi być odpowiednio dostosowany.

Ciekawą cechą programu WinRT jest ogłoszenie różnych, ale podobnych API dla każdej platformy deweloperskiej. Jak być może już wiesz, wszystkie nazwy metod są reprezentowane przez camelCased [2], podczas gdy deweloperzy w C++ i .NET widzą nazwy metod jako PascalCased [3]. Inną, bardziej drastyczną zmianą jest automatyczne mapowanie między interfejsami C++ i .NET. Dlatego. Programiści .NET nie muszą zajmować się przestrzenią nazw Windows.Foundation.Collections, wystarczy, że nadal korzystają z przestrzeni nazw System.Collections.Generic. Interfejsy IVectorView <T>i IMapView<K, V> będą w czasie działania przekształcane odpowiednio w interfejsy IReadOnlyList <T>oraz IReadOnlyDictionary<TKey, TValue>.

Warto zauważyć, że nazwy interfejsów w C++/WinRT są w pewnym stopniu dokładniejsze. Interfejsy te służą do reprezentowania niektórych widoków kolekcji, ale interfejs ten nie gwarantuje, że sama kolekcja jest niezmienna. Nawet wśród tych z doświadczeniem. Częstym błędem wśród twórców .NET jest zakładanie, że typ ReadOnlyCollection to kopia kolekcji niezmiennej, podczas gdy w rzeczywistości jest to tylko opakowanie kolekcji aktywnej (zobacz post Andrew Arnotta o tym samym tytule, aby uzyskać więcej informacji o kolekcjach tylko do odczytu, zamrożonych i niezmiennych).

Chociaż interfejs IList <T>ma wszystkie te same elementy co interfejs IReadOnlyList <T>i wszystkie listy typu IList <T>mogą być reprezentowane jako listy tylko do odczytu, IList <T>nie dziedziczy z IReadOnlyList<T>, co może być ciekawe do poznania. Wyjaśnił Immo Landwerth,

Powód, dla którego to działa, jest taki, że te interfejsy tylko do odczytu są czysto podzbiorami interfejsów do odczytu i zapisu, co wydaje się rozsądnym założeniem. Niestety, to założenie nie odpowiada rzeczywistości, ponieważ każda metoda na każdym interfejsie na poziomie metadanych ma własny slot (co sprawia, że implementacje interfejsów działające działają).

Innymi słowy, jedyną szansą na wprowadzenie interfejsu tylko do odczytu jako jakiejś zmiennej klasy bazowej jest powrót do . NET 2.0, czyli w momencie pierwotnego powstania. Gdy zostanie w pełni wdrożony, jedyną możliwością jest dodanie znaczników kowariantnych i/lub inwerterowych (reprezentowanych jako "in" i "out" w VB i C#).

Zapytany, dlaczego nie ma interfejsu IReadOnlyCollection<T>, Immo odpowiedział,

Rozważaliśmy ten projekt, ale uznaliśmy, że dodanie typu zawierającego jedynie atrybut Count nie wniesie dużej wartości do podstawowej biblioteki. W zespole bibliotek bazowych uważamy, że jeśli API zaczyna się od minus 1000, to nawet dodanie pewnej wartości nie wystarczy, by uzasadnić dodanie. Uzasadnienie dodawania nowych API wiąże się także z kosztami, na przykład deweloperzy będą mieli więcej koncepcji do wyboru. Na początku myśleliśmy, że dodanie tego typu sprawi, że kod będzie lepiej działał w określonych sytuacjach, gdzie po prostu chcemy zliczyć i zrobić z nim coś ciekawego. Na przykład masowe dodawanie do istniejącej kolekcji. Jednak w tych sytuacjach zachęcaliśmy ludzi do korzystania wyłącznie z interfejsu IEnumerable<T>, a <T>w szczególnym przypadku posiadania instancji implementującej interfejs ICollection. Ponieważ wszystkie nasze wbudowane typy kolekcji zaimplementowały ten interfejs, nie odnotowano żadnej poprawy wydajności w tych najczęstszych scenariuszach. A tak przy okazji, <T>metoda rozszerzenia Count() dla IEnumerable również to potrafi.

Te nowe interfejsy są dostępne dla . NET 4.5 oraz . NET for Windows 8。

Notatki tłumaczeniowe

[1] Biblioteka Klasy Podstawowej, w skrócie BCL. Aby uzyskać więcej informacji o bibliotece klas podstawowych, prosimy o udział w MSDN.

[2] Wielbłądowa Otoczka, nomenklatura garbna, znana również jako przypadek wielbłąda dolny. Format jest taki, że pierwsze słowo zaczyna się od małej litery; Pierwsza litera drugiego słowa jest pisana wielką literą, na przykład: firstName, lastName.

[3] PascalCased, nomenklatura Pascal, znana również jako przypadek górnego wielbłąda. Format polega na tym, że pierwsza litera każdego słowa jest pisana wielką literą, na przykład: FirstName, LastName, CamelCase.




Poprzedni:.NET/C# Platforma Licencjonowania Oprogramowania [Kod źródłowy]
Następny:JS Mining – Jak Monero eksploatuje przez web mining?
Zrzeczenie się:
Całe oprogramowanie, materiały programistyczne lub artykuły publikowane przez Code Farmer Network służą wyłącznie celom edukacyjnym i badawczym; Powyższe treści nie mogą być wykorzystywane do celów komercyjnych ani nielegalnych, w przeciwnym razie użytkownicy ponoszą wszelkie konsekwencje. Informacje na tej stronie pochodzą z Internetu, a spory dotyczące praw autorskich nie mają z nią nic wspólnego. Musisz całkowicie usunąć powyższą zawartość z komputera w ciągu 24 godzin od pobrania. Jeśli spodoba Ci się program, wspieraj oryginalne oprogramowanie, kup rejestrację i korzystaj z lepszych, autentycznych usług. W przypadku naruszenia praw prosimy o kontakt mailowy.

Mail To:help@itsvse.com