Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 69
Текст из файла (страница 69)
Синтаксис подобен принятому в языках С++ и дача. Метод ТогеасЬ для итерации по массиву более элегантен, и как будет покааано далее, его применение позволяет испольэовать тот же код для итерации по коллекциям, которые могут и не быть массивами. На заметку! Для итерации по массивам и коллекциям предпочтительно применять Тогеасц. В результате появляется возможность измвнять позднее тип контейнера, при этом блок Тогеасп остается неизменным.
Если же вместо этого используется цикл Тог, возможно, придется изменить метод доступа к каждому индивидуальному элементу. Вдобавок Гогеасп работает и с массивами, у которых нижняя граница индекса не равна О. Часто имеет смысл использовать зубчатые массивы вместо прямоугольных. Например. можно читать информацию из базы данных, и каждый элемент массива верхнего уровня может представлять коллекцию, в которой каждая подколлекция может иметь широко варьируемое количество элементов.
Если большинство подколлекций содержат лишь по нескольку элементов, а одна из них — 100 элементов, то прямоугольный массив в этом случае тратит огромное количество места в памяти впустую, поскольку ему нужно выделять 100 вхождений для каждой подколлекции, независимо от реального количества элементов. Зубчатые массивы обычно более эффективно используют память.
но зато обращение к их элементам требует большей осторожности, поскольку нельзя полагаться на то, что каждый подмассив содержит одно и то же количество элементов. На заметку! Зубчатые массивы потенциально могут быть более эффективными, поскольку обычно состоят из одномерных массивом с нулевым минимальным индексом, которые СЬВ представляет в виде векторов, как было описано выше в главе. 260 Глава 9 Типы коллекций С момента своего появления платформа .ХЕТ Рта)певюгК включала множество типов коллекций.
предназначенных для управления всем — от расширяемых массивов Аггауьаяг, очередей Оиеие, стеков Бгаск и даже словарей — через класс НаяЬТаЬ1е. С годами новые версии .ХЕТ РгагпевюгК расширилн и усовершенствовали эти типы. В общем случае коллекция — это любой тип, который может содержать в себе наборы объектов и реализует интерфейс ТЕпивегаЬ1е или ТЕпивегаЬ1е<т>. Объекты в таком наборе обычно имеют между собой отношения, определяемые предметной областью. Далее предполагается, что вы уже знакомы с необобщенными типами коллекций и интерфейсами коллекций, которые определены в пространствах имен Яуяеев. Со11ессаопя и Буяпев.
Со11ессаопя. Брес1а11яе<( в .ХЕТ 1.1. В МБРХ доступна масса документации на эту тему. В дальнейшем старые типы коллекций будут называться необобщенными типами коллекций, чтобы отличать их от новых типов колленций и интерфейсов, определенных в пространствах имен яуясев.со11есс1опя.бепег1с и Яуягев.Со11есг1опя.ОЬЯес1Мос(е1. Сравнение ХСо11ес~1оп<т> и 1Со11ес~хоп Наиболее очевидные дополнения к типам колленций, которые появились в .ХЕТ 2.0 Ргаше)чогК, являются типы, определенные внутри пространства имен Яуягев.
Со11ессаопя. Сепегас. Обобщения более подробно рассматриваются в главе 11. Эти типы строго типизированы, что предоставляет компилятору большие возможности для обеспечения безопасности типов за счет выявления ошибок несоответствия типов на этапе компиляции. Вдобавок, когда они используются для хранения типов значений, они намного более эффективны, поскольку исключают необходимость в упаковке. Корнем всей системы обобщенных типов коллекций вполне можно считать ТСо11есгаоп<Т>.
Ниже приведено его объявление: риЬ11с Тпсегласе 1Со11есгаоп<Т>: 1ЕпивегаЬ1е<Т>, 1ЕпивегаЬ1е Тпс соим ( Бес) ) Ьоо1 1яаеайоп1у ( Бес) ) чо(с) Ас(и'( Т Тгев ); чо1и С1еяг() ) Ьоо1 Соппа1пя( Т 1Сев )) чоаи СоруТо( Т(] аггау, 1пс аггау1ппех )) Ьоо1 Еевоче( Т Тгев ); Для сравнения показано также определение необобщенного интерфейса 1Со11ессгош риЬ11с гппеггасе 1Со11есгаоп: ТЕпивегаЬ1е ( Тпп Соил< ( реп) ) Ьоо1 1яЯупспгощяеи ( дегп ) оЬ)есг Яупскоос ( лещ ) чогб СоруТо( Аггау аггау, Тпг Тпиех ) Рассмотрим отличия между ними и то. что они означают для кода.
Необобщенным коллекциям недостает универсального интерфейса управления содержимым ноллекции. Например. оба необобщенных типа — Бгаск и Оиеие — имеют метод С1еаг для очистки своего содержимого. Как и можно было ожидать, оба они реализуют интерфейс 1Со11есгаоп. Однако поскольку 1Со11есс1оп не содержит никаких модифицирующих Массивы, типы коллекций и итераторы 261 методов, обычно полиморфно трактовать в коде экземпляры этих двух типов нельзя.
Поэтому всегда приходится выгюлнять приведение переменной экземпляра к типу Бгаск, чтобы вызвать Бгзск. 01езг, и приводить к типу Спеце, чтобы вызвать Ссеое. С1еаг. 1Со11есг1оп<Т> помогает решить эту проблему за счет объявления методов для модификации коллекции. Как в большинстве универсальных решений, это не обязательно применимо ко всем ситуациям. Например, в 1Со11есгзоп<Т> также объявлено свойство 1зРеас!Оп1у, поскольку иногда нужно представлять неизменяемую коллекцию. Для таких экземпляров вызовы методов А<го, С1езг и Кетотге приведут к генеращти исключения 1пча1160регаг1опЕхсергьоп, На заметку! В интересах производительности рекомендуется, чтобы вызывающий код определял, разрешены ли такие операции, проверяя свойство Тзнеагтоп1у и таким образом вообще избегая исключений.
Разумеется, если конечным результатом Тзеезг!Сп1у, возвращающего сгое, окажется генерация исключения, то никакого выигрыша не будет. Поскольку главное назначение 1со11ессзоп<т> — обеспечить более высокую безопасность типов, для 1Со11ессьоп<Т> имеет смысл предоставление собственной строго типизированной версии СоруТо. В то время как методу 1Со11есгьоп. СоруТо известно, что его первым параметром является массив, при этом может приниматься ссылка на Бузкеп.лггзу, ТСо11есгьоп<Т>.СоруТо впервом параметре передается конкретный тип массива. Ясно,что методу 1Со11естзоп<Т>.СоруТоможнопередавать только одномерные массивы.
Фактически необобщенный метод 10о11есг1оп.СоруТо также принимает только одномерные массивы,но поскольку компилятор не может определить размерность типа Б уз Сегл. Актау во время компиляции. при передаче правильной реализации 1со11есс1оп. соруто массива с более, чем одним измерением будет сгенерировано исключение времени выполнения Агооглепсехсерс1оп. Обратите внимание на слова "правильной реализации".
Это правило должен знать как вызывающий код, так и тип, который реализует 1со11есс1оп. Дополнительная информация о типе в 1со11есгьоп<Т>. СоруТо не только предохранит от ошибки код, вызывающий этот метод, и код, его реализующий, но и обеспечит повышенную эффективность. Все обобщенные типы коллекций реализуют и 1со11есс1оп<т>, и 1со11есгьоп. Оба интерфейса предоставляют удобный доступ к типу контейнера.
Любые методы в 1со11ессзоп, перекрывающие 1со11ессзоп<т>, должны быть реализованы явно. На заметку! При определении собственных типов коллекций они должны наследоваться от со11ессьоп<т> из пространства имен со11ессзоп.оь1ессмог!е1, если только нет веской причины поступить иначе. Например, Со11есгзоп<Т> может предоставлять некотОруЮ функциональность, которая не нужна, или же требуется реализовать собственный способ хранения элементов в коллекции и защищенные виртуальные методы, которые можно переопределять для управления поведением коллекции. Если не производится наследование от со11есгьоп<т>, работа окажется более трудной, поскольку придется реализовать большую часть того, что уже реализовано в со11ессьоп<т>.
Создавая собственный тип словаря, наследуйте его от кеуепсо11ессьоп<ткеу, т1сет>. тип ьззс<т> не предназначен для того, чтобы служить базовым классом, поскольку не предоставляет никакой возможности переопределять свое поведение. Синхронизация коллекций В Тсо11ессьоп присутствует одно средство. которого недостает его обобщенному аналогу, а именно — обеспечение многопоточной синхронизации для всех коллекций. По умолчанию большинство типов коллекций не синхронизировано. Для определения 262 Глава 9 того, синхронизирована ли коллекция, служит свойство 1эзупспгоп1кед.
В большинстве случаев, включая Буэсегл. Актау, ответ будет отрицательным (га1эе). Однако иногда синхронизация требуется при обращении к коллекции из нескольких потоков. Существует пара способов управлять синхронизацией коллекций, возвращающих га1эе из 1Со11ессзоп. 1эзупслгопзэе<ь Основной способ предусматривает использование свойства 1со11ессзоп. Бупсяоос, возвращающего объект, который впоследствии можно применить с Буэсеп. Иопзсог — обычно с помощью оператора 1осх, — чтобы защитить доступ к коллекции. Такой способ обеспечивает большую гибкость доступа к коллекции, поскольку при этом четко контролируются моменты захвата и освобождения блокировки. Однако также потребуется обеспечить корректную обработку блокирования. поскольку коллекция не пытается самостоятельно захватить блокировку.
На заметку! Выбор способа реализации синхронизации — классический пример компромиссного инженерного решения, которое приходится принимать при проектировании новых коллекций, реализующих Тсо11ессзоп. Синхронизацию можно реализовать внутри коллекции, но тогда клиенты, которым она не нужна, будут нести излишние затраты. Синхронизацию также можно вынести наружу, реализовав 1со11есс1оп. Бупсйоос, но тогда на клиента возлагается обязанность правильно управлять синхронизацией. Делая тот или иной выбор, следует учитывать особенности домена приложения.
В некоторых случаях типы коллекций просто возвращают для 1Со11ескзоп. Б упсяоо с ссылку сп1э. Поэтому лучше никогда не синхронизировать доступ к коллекции, передавая ссылку на нее напрямую Б у эеегл. Мопзк о г. Вместо этого всегда используйте объект, полученный через свойство Бупсйоос, даже несмотря на то, что оно может в действительности вернуть Сп1 э. В качестве альтернативы ручному управлению Бупс1,осй большинство необобщенных типов коллекций из стандартной библиотеки реализуют метод Бупспгоп1 хегг, который возвращает объект-оболочку коллекции, управляющий блокировкой синхронизации.












