Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 70
Текст из файла (страница 70)
Аналогичный шаблон можно попробовать применить при создании собственных типов коллекций. Используя оболочку, возвращенную методом Бупслгоггзкесг, клиентский код, работающий с этой коллекцией, не должен изменяться, чтобы позволить работу в многопоточной среде. При реализации собственных коллекций всегда позволяйте клиентам выбирать возможность использования синхронизации и никогда не навязывайте ее обязательное применение. Совет. Если требуется синхронизация внутри коллекций, используемых в многопоточной системе, настоятельно рекомендуется использовать типы коллекций из Буэгегк. Со11есгзопэ. Сспсоггепш Эти типы были добавлены в .ИЕТ 4.0 командой платформы параллельных вычислений М~сгозой, и их техника блокировки отлично настроена на обеспечение эффективности в многопоточных средах с параллелизмом.
Списки Одной вещью, которая отсутствует 1Со11ескзоп<Т>, и на то есть веская причина, является операция индекса, которая позволяет обращаться к элементам внутри коллекции с использованием знакомого синтаксиса доступа к массиву. Дело в том, что операция индекса нужна не всем конкретным типам, реализующим 1Со11есгзоп<Т>, а в некоторых случаях она и вовсе не имеет смысла. Например, операция индекса для списка целых чисел могла бы, скорее всего, иметь параметр типа зпг, в то время как тип словаря должен был бы принимать параметр типа, совпадающего с типом ключа такого словаря. Массивы, типы коллекций и итервторы 263 Если определяется коллекция, для которой имеет смысл индексировать элементы, то необходимо, чтобы эта коллекция реализовала 111яс<т>.
Конкретные обобщенные типы коллекций-списков обычно реализуют интерфейсы 11.). я с<т> и 1 11 яь. интерфейс 1ььяк<Т> реализует 1СО11ескьоп<Т>, а интерфейс 1ььяг реализует 1Со11есггоп. поэтому любой тип, являющийся списком, также является коллекцией. Интерфейс 111яс<т> выглядит слелутощим образом: рпы1с 1пгеглзсе 111як<т>: тсс11есстоп<т>, 1еппвегаые<т>, 1еппвегэые ( т кЫя[ 1пг Епбех ) ( оес; яег; ) 1пт 1пбехот ( Т усев ) ) чокб 1пяегг( 1пг 1пбех, Т 1сев )т нозб АевонеАг( Тпг Тпбех )т ) Интерфейс 111вс немного больше: рпыгс 1псегтасе 1ьаяс: 1со11есгбоп, 1еппвегаые Ьоо1 1ярзхебягге ( дев) ) Ьос1 1впеабоп1у ( дев) ) оптесг СЫя[ 1пт Тпбех ) ( деш ) Тпс Абб( оЬ)ест нз1пе )~ нотб С1еаг(); Ьоо1 Сопкатпв( опт'ест ча1пе )т Тпг 1пбехОГ( сЬ)есг ча1це )т чсьб 1пяегс( Тпг Тпбех, оЬт'есс на1пе )т чо1б левоне( оЬ)есс на1пе )т чолб Еевонелк( 1пк 1пбех )т как видите, интерфейсы 1ьбяс<т> и 111яс частично перекрываются,но в 1ьуяс присутствует множество полезных свойств и методов, которых не может иметь такой обобщенный контейнер, как 111яс<т>, или любой другой обобщенный контейнер, созданный вами.
как в случае с 1со11ессуоп<т> и 1со11есс1оп,типичный подход предусматривает реализацию обоих интерфейсов. Методы 111яс, которые перекрывают по функциональности соответствующие методы 111яг<т>, должны быть реализованы явно, чтобы единственным способом обратиться к ним было явное преобразование экземпляра к типу 111як. На заметку! Обычно при реализации собственных списочных типов необходимо производить наследование от типа со11есс1оп<т> из пространства имен яуясев.со11ессьопя. ОЬбесвнобе1. Словари В .)т)ЕТ 2.0 ргатпетног)к появился тип 1РТсвгопагу<ТКеу, ТЧа1це> — обобщенный, а потому строго типизированный аналог 1РТсЫопвгу. Как обычно, конкретные типы, реализующие 1Р1сс1опагу<ткеу, тча1це>, должны также реализовать 1Р1сс1опагу. Между ними есть много перекрытий, но обобщенный интерфейс объявляет более безопасные в отношении типов версии некоторых свойств и методов, объявленных в 1РТскбопагу.
Однако в 1РТсв1опагу<ткеу, тув1се> присутствует также н новый метод по имени тгубегча1ие, который можно использовать для получения значений на основе заданных ключей. Этот метод возвращает значение в выходном параметре, а само возвращаемое значение говорит о том, присутствует ли элемент с таким ключом 264 Глава 9 в словаре. Хотя того же можно добиться, используя операцию индекса и перехватывая исключение кеуног еоппсехсерсаоп, когда элемента в словаре нет, всегда более эффективным будет код, избегающий исключений, если известно, что искомого элемента может не оказаться в словаре. Во-первых, исключения не эффективны для управления потоком выполнения. поскольку дорого обходятся.
Во-вторых, при этом игнорируется тот факт, что исключение должно представлять действительно исключительное событие. Использование исключений для управления потоком выполнения означает обработку с нх помощью ожидаемых событий. Вызовы методов Тгу... теперь повсеместно встречаются в . НЕТ г гатпеиюг)<, поскольку разработчики платформы предприняли значительные усилия для устранения узких мест эффективности вроде описанного выше использования исключений.
На заметку! При реализации обобщенных словарей существуют два варианта выбора, от чего наследовать реализацию, Для начала можно использовать яогсеб01сс1опагу<ткеу, тчз1це>, который обеспечивает время доступа О))ор п) и реализует 1рассаопагу<ткеу, туа1це> в качестве интерфейса коллекции. Однако вполне можно отдать предпочтение кеуебСо11есгаоп<ТКеу, Туа1це> из пространства имен яузсев. со11есс1опз. Оь! ессмосе1. Хотя этот класс на самом деле не реализует интерфейсов словарей, он обеспечивает время доступа О! ! ) в большинстве случаев, Подробности ищите в документации МЯОМ.
Наборы В .НЕТ 3.5 Ргашечгог)к появился еще один полезный класс коллекций по имени нэзпяес, который определен в пространстве имен Яузсев. со11ессьопз. Йепегас. Класс назйбек реализует типичные операции над множествами, которых можно было ожидать. Например, с помощью вызова метода Гпсегзессиась можно модифицировать набор, чтобы он содержал пересечение текущего множества элементов с элементами, содержащимися в заданном экземпляре типа 1епцпегзь1е<т>. А метод Опьопнась позволяет модифицировать текущий набор так, чтобы он включал объединение двух наборов. К другим полезным методам относятся 1ззсЬзеСОТ.
1ззцрегзеСОГ, Ехсерккасп, яуавесг1сехсерснась, сопса1пз и тд. Это лишь несколько нз удобных методов, доступных в наборах. На заметку! Обратите внимание, что различные методы операций над множествами, реализованные назпяещ принимают параметры типа Гепцглегзь1е<т>. Это очень удобно, поскольку позволяет передавать в качестве параметра этим методам любой тип коллекции, а не только экземпляры назь яеш Как зто принято в операциях над множествами, к экземплярам Нззпяег можно добавлять только уникальные значения. Например, если к экземпляру Назпзет<1пг> уже добавлены значения 1, 2 и 3, то вставить целое число, совпадающее с одним из этих значений, не удастся.
По этой причине метод АсЫ возвращает булевское значение. указывающее на то, удалась ли операция. Гвнерировать исключения в таких случаях было бы неэффективно. поэтому результат обозначается возвращаемым значением метода АсЫ. Зуз~еп).Со11ес~1опз.ОЬ~есйМобе1 При определении собственных типов коллекций наиболее удобными типами окажутся те, что определены в пространстве имен яузгет.
Со11есгаопз. ОЬч есСМог)е1. Г)о возможности реализации должны наследоваться от объектов из этого пространства Массивы, типы коллекций и итераторы 265 имен. Оно содержит только пять типов, и сам факт существования такого пространства имен является предметом дискуссии. Выло две главных причины вынести эти пять типов в отдельное пространство имен. Во-первых, в среде Ч!япа! Вав!с уже есть тип Со11есгаоп, реализованный в пространстве имен, импортируемом по умолчанию, и в команде Ч!яма) Вая!с предположили, что пользователи УВ будут введены в заблуждение, увидев два типа с одинаковыми именами, но с совершенно отличающимся поведением, в окне !пте1!!Бепяе.
Во-вторых, в команде, занимающейся разработкой библиотек базовых классов !Вазе С!аяя ЬтЬгаг!ея — ВСЬ), решили, что пользователям редко понадобятся типы из этого пространства имен. Со временем выяснится, так ли это. С другой стороны, эти типы исключительно полезны для написания библиотек кода, используемых другими. Одно из руководств М1сгояой советует создавать подклассы этих типов при разработке коллекций, даже если только требуется предоставить более выразительное имя, описывающее коллекцию, и обеспечить удобное место для расширений. Эти типы весьма удобны при определении собственных типов коллекций. Для получения поведения коллекции по умолчанию, включая реализации 1Со11есгтоп<Т>, 111яс<т> и 1еппквегзЬ1е<т>,необходимо унаследовать свой тип от со11ессаоп<т>.












