Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 93
Текст из файла (страница 93)
Однако его потребуется оснастить необходимыми средствами для преобразований в тип с(опЬ1е и обратно, а также операцией умножения и компонентными типами. Эта структура Сотр1ех<Т> не может служить руководством по созданию представлений комплексных чисел. На самом деле это просто довольно надуманный пример. предназначенный для того, чтобы проиллюстрировать многие нюансы, с которыми придется иметь дело при создании эффективных обобщенных типов. С примерами применения некоторых из описанных приемов придется столкнуться при работе с обобщенными контейнерами, представленными в библиотеке ВСЬ.
Динамическое создание конструируемых типов Учитывая динамическую природу СЬК и тот факт, что на самом деле классы и код генерируются во время выполнения, вполне естественно предположить возможность конструирования закрытых типов из обобщений во время выполнения. До настоящего момента все примеры этой книги имели дело с созданием типов во время компиляции. Эта функциональность проистекает из естественного расширения спецификации метаданных для обслуживания обобщений. Тип Вузгеп. туре — краеугольный камень функциональности, когда нужно работать с типами динамически внутри СЬН, и естественно, он был расширен для того, чтобы иметь дело также и с обобщениями.
Некоторые ориентированные на обобщения методы Буясет. Туре самоочевидны благодаря их Обобщения 355 именам; к ним относятся Яесяепег1сдгсявепсв, Яесяепег1сРагвпесегСопвсгвгпсе и Сессепег1стурере11п1сбоп. Эти методы полезны, когда уже есть экземпляр Яувсеи. Туре, представляющий закрытый тип.
Однако то, что делает все намного интереснее — вто метод Махеоепег1сТуре, который позволяет передать массив объектов я уз тем. Туре, представляющих типы, которые должны быть использованы в списке аргументов для создания результирующего конструируемого типа. Тех из вас, кто имеет опыт работы с шаблонами С++, обобщения могут время от времени разочаровывать, поскольку им недостает статических возможностей шаблонов. Однако динамические возможности обобщений в конечном итоге перевешивают.
Например, создание механизма анализа некоторого языка, основанного на ХМЬ, в нотором определяются новые типы на основе обобщений, становится очень простым. Ниже приведен пример использования метода Махепепеггстуре: ив1по Яувсеп) ивгпд Яувсеи.со11ес11опв.оепеггсг рпьугс с1аяв ЕпсгуРогпс ( ясасгс чогб Мвгп() ( 111яс<1ПГ> 1ПГХ1ЯГ (111ВГ<1ПГ>) СГЕВГЕС1ОЯЕбТУРЕ<1ПГ>( ГУРЕОТ(ХХЯГ<>) ) 1Швс<бопЬ1е> боиЬ1еХ1вс = (1дгяс<боиЬ1е>) СГЕВГЕС1ОЯЕбТУРЕ<бсиЬ1Е> ( ГУРЕОТ(ХХВГ<>) ) 1 Сопяо1е.нг11еХ1пе( гпГХХяс ); Сопяо1е.нггсеьапе( бопЬ1еьгяс ) 1 ) вкясгс оЬ)есг СгевсеС1овебтуре<Т>( Туре оепег1стуре ) ( Туре[) ГуреАгоитепсв = Гуреог( т ) Туре с1овебТуре = депеггсТуре.МвхеоепеггсТуре( ГуреАгппвепкв ); гесигп Асс1чясог.сгеасе1пясвпсе( с1озебТуре ) 1 Основная часть этого кода содержится внутри обобщенного метода сгезгеС1овеб Туре<Т>.
В общих чертах вся работа выполняется через ссылки на Туре, созданные из доступных метаданных. Сначала должна быть получена ссылка на обобщенный, открытый тип Х1яс<Т>, который передан в виде параметра. После этого просто создается массив экземпляров Туре для передачи методу Мв)геЯепег1стуре,чтобы получить от него ссылку на закрытый тип. Как только эта стадия завершена, единственное, что остается — это вызов Сгеасе1пясапсе на классе яуясев. Ассбчасог. Класс яуягещ.Асггчагог — это средство, которое должно использоваться для создания экземпляров титюв,известных только во время выполнения.
В данном случае вызывается конструктор по умолчанию для закрытого типа. Однако Асг1чагог имеет перегрузки сгеаге1пвгапсе,которые позволяют вызывать конструкторы, принимающие параметры. На заметку) Чтобы получить экземпляр Туре для типов, вместо метода Туре .Сестуре применяется операция гуреот. Если тип известен во время компиляции, то операция гуреот сразу осуществляет поиск по метвданным вместо того, чтобы делать зто во время выполнения, что более эффективно. 356 Глдэз 11 После запуска предыдущего примера закрытые типы выводятся на консоль с указанием их полностью квалифицированных имен типов, тем самым доказывая правильность создания закрытых типов. Возможность создания закрытых типов во время выполнения — еще один мощный инструмент, предназначенный для создания высокодинамичных систем. Можно не только объявлять обобщенные типы в коде, чтобы получать гибкий код, но также создавать закрытые типы из этих обобщенных определений во время выполнения. Задумайтесь на минуту о круге задач, которые можно решить с помощью такой техники, и вы поймете, что обобщения — исключительно мощное дополнение к С№ и СЬК.
Резюме В этой главе было показано, как объявлять и использовать механизм обобщений в С№, включая обобщенные классы, структуры, интерфейсы, методы и делегаты. Также рассматривались обобщенные ограничения, которые необходимы для того, чтобы компилятор создавал код, в котором на аргументы типа, предоставляемые обобщенным типам во время выполнения, накладываются некоторые функциональные предположения. Благодаря обобщениям, типы коллекций получают ощутимое и реальное преимущество в отношении эффективности и безопасности.
Обобщения не только позволяют генерировать более эффективный код при использовании типов значений в качестве параметров, но также придают компилятору больше мощности для обеспечения безопасности типов. Кэк правило, всегда следует отдавать предпочтение безопасности типов времени компиляции перед безопасностью типов времени выполнения. Таким образом, сбои во время компиляции можно исправить до сдачи программного обеспечения в эксплуатацию.
Сбой во время выполнения, в зависимости от ситуации. может обойтись конечному пользователю кругленъкую сумму и скомпрометирует вас как разработчика. Поэтому всегда снабжайте компилятор максимальными возможностями контроля безопасности типов, чтобы он делал то, для чего предназначен — быть вашим другом. В следующей главе рассматривается тема многопоточности в С№ и исполняющей системе .1ЧЕТ. Вместе с многозадачностью затрагивается и не менее важная тема синхронизации. глава 12 Многопоточность в СИ П ростое упоминание о многопоточности иногда вселяет страх в сердца некоторых программистов.
Для остальных — это хороший вызов. Независимо от того, как вы реагируете на нее, знайте, что многопоточность — это область, усеянная минными полями. Если вы не отнесетесь к этому с должным прилежанием, ошибка многопоточности неожиданно возникнет и натворит много бед, причем там, где вы этого не ожидали. Ошибки многопоточности относятся к одним из самых трудно обнаруживаемых. Их сложно найти на однопроцессорной машине. но стоит добавить дополнительные процессоры и ядра — и обнаружить эти ошибки станет еще труднее.
В действительности, некоторые ошибки многопоточности никак не проявляются до тех пор. пока приложение не будет запущено на многопроцессорной машине, поскольку это единственный способ получить настоящую параллельную многопоточность. По этой причине разработчик многопоточного приложения должен тестировать его именно на многопроцессорной машине. В противном случае есть риск выпустить продукт со скрытыми ошибками многопоточности.
Я помню. как будто это было вчера: у моего бывшего работодателя случилось так. что мы поспешили передать нашу золотую мастер-копию производителю компакт-дисков и получили сотни тысяч дисков, а потом напоследок получилось протестировать приложение на многопроцессорной машине. Ведь в те дни многопроцессорные машины были редкими и мало доступными. Стоит ли говорить, что это послужило наглядным уроком всей команде разработчиков, когда ужасная ошибка была выявлена перед самым выпуском продукта в свет7 Многопоточность в СФ и .МЕТ Несмотря на то что многопоточные среды за годы принесли с собой множество сложностей и проблем, да и продолжают это делать.
СЬЕ и базовая библиотека классов .НЕТ смягчают многие связанные с этим риски и предлагают ясную модель, на основе которой можно строить приложения. По-прежнему справедливо утверждение, что наибольшей сложностью при разработке высококачественного многопоточного кода остается синхронизация. Платформа .НЕТ РгагпевюгК позволяет, как никогда раньше, легко создавать новые потоки и использовать управляемые системой пулы потоков и предоставляет интуитивно понятные объекты, помогающие синхронизировать потоки между собой. Однако в ваши обязанности входит обеспечить правильное применение этих объектов.
Управляемые потоки — это виртуальные потоки, в том смысле, что они не обязательно однозначно отображаются на потоки операционной системы. Управляемые потоки действительно работают параллельно, но было бы ошибкой предполагать, что 358 Глава ) 2 поток операционной системы, выполняющий в данный момент управляемый код для одного иэ управляемых потоков, будет выполнять код только этого потока. Фактически, в текущей реализации СЬК поток операционной системы выполняет управляемый код для нескольких управляемых потоков в нескольких доменах приложения. В итоге иужио подчеркнуть: ие делайте никаких предположений о какой-либо корреляции между потоками операционной системы и управляемыми потоками. Если вы доберетесь до потока ОС, используя уровень р/!пуо)ге для выполнения прямых вызовов ЪЧШ32, убедитесь, что ииформадия о потоке платформы применяется только в отладочных целях, и иа яей ие осиоваиа какая-либо программная логика.















