Нэш Трей - C# 2010. Ускоренный курс для профессионалов (2010) (1160865), страница 29
Текст из файла (страница 29)
Поскольку сгенерированное компилятором имя типа неизвестно, экземпляр переменной должен быть объявлен как неявно типизированная локальная переменная с применением ключевого слова чаг, как зто делалось в коде примера. Также обратите внимание, что сгенерированный компилятором тип является обобщенным и принимает два параметра типа. )оперировать новый тип для каждого анонимного типа, содерхкащего два типа с одними и теми же именами полей, для 104 Гааза 4 компилятора было бы неэффективно. Приведенный выше вывод указывает на то, что действительный тип евр1оуее1пуо выглядит следующим образом: <>1 Апопувочзтуре0<яузгев.ягтгпд, яузгев.1пг32> Поскольку анонимный тип для созговет1пуо содержит столько же полей с теми же именами.
то сгенерированный обобщенный тип используется повторно, и тип спяговег1пто будет выглядеть так: <>1 Апопушооятурео<яуягев.ягт1пя, яуягев.ягг1пч> Если анонимный тип для счзговет1пто включает поля с именами, отличными от применяемых в евр1оуеетпуо, то будет объявлен другой обобщенный анонимный тнп.
Теперь, когда вы ознакомились с основами анонимных типов, рассмотрим сокращенный синтаксис для их объявления. В следующем примере обратите внимание на операторы, выделенные полужирным; чз1пд Яуягев; рчЬ11с с1аяз Сопчепг1опа1Евр1оуее1пто ( ровттс Сопчепгтопа1Евр1оуее1пто( ягт1пц Маше, 1пг 1с( ) ( гптя.паве = Маве; гЬ1з.10 = 10) ) рнЬ11с ягттпд Маше ( оег ( тегчтп павев ) зег ( паве = ча1че; ) рчЬ11с "пг 1с( ( Яег ( тегчгп ТО яег ( ХО = ча1че; ) рт1чаге ягттпд паве; рг1чаге гпг 1с(; ) рчЬ11с с1аяз Епгтурогпг ягаг1с чогб Иа1п() ( Сопчепгтопа1Евр1ауее1пто о1охвр1оуее = пе» Сопчепг1опа1Евр1оуее1пго( "Осе", 42 ); чат евр1оуеегпуо = пе» ( о1дквр1оуее.Маше, о1с)двр1оуее.тй ); вгг1пд Иаяе " тале") Хпг Хб = 12Э4; чат ооягвяегхпео = пе» ( паве, хо )) Сопяо1е.»т1геЕХпе( "Значение Маше в евр1оуее1пго: (0), 1О: (1)", евр1оуее1пго.каше, евр1оуее1пто.1с( ); Сопяо1е.кт1ге11пе( "Значение Маше в спвговег1пго: (0), 1с(: (1)", спяговег1пго.каше, спяговег1пто.1о )в Сопяо1е.кггге11пе( "Анонимным типом сейчас является: (0)", евр1оуее1пго.6егтуре() ); Классы, структуры и обьекты 105 В целях иллюстрации объявлен тип Сопчепгзопа1Еяр1оуее1пго, который не является анонимным.
Обратите внимание, что в точке, где создается экземпляр анонимного типа для епр1оуеетого, не были указаны имена полей, как раньше. В данном случае компилятор использует имена свойств типа сопчепг1опз1еггр1оуее1пго, который является источником данных. Этот же прием работает и для локальных переменных, как видно в объявлении экземпляра сцзгоглегтпто. В данном случае сцэгопег1пго— анонимный тип, реализующий два свойства с именами Нагэе и 1с1, доступные для чтения/записи. Объявления членов анонимных типов, использующие такой сокращенный стиль. называются инициализаторами проекции 1рго)есттоп Питта)1гегз)'. Если вы просмотрите скомпилированную сборку в 1ЬПАЭМ, то заметите, что сгенерированными типами для анонимных типов будут классы.
Каждый такой класс помечен модификаторами ргучэсе и зеа1ес1. Однако зти классы исключительно примитивны и не реализуют ничего подобного финализатору или 151эрозаЬ1е. На заметку! Анонимные типы, даже будучи классами, не реализуют интерфейс тотэроээьте. Как будет упомянуто в главе 13, общее требование для типов, содержащих одноразовые (б)зроэаЫе) типы, заключается в том, что они тоже должны быть одноразовыми.
Но поскольку анонимные типы таковыми не являются, следует избегать помещения экземпляров одноразовых типов внутрь них. Будьте осторожны, чтобы не потерять информацию об анонимном типе. Если экземпляры анонимных типов помещены в список 5 уз кесл. Езз щ то как впоследствии планируется приводить их обратно к анонимному типу' ? Помните, что Вузкегл. Ь1зс хранит ссылки на Еузсегэ.
Оь)есщ Даже несмотря на то, что анонимные типы наследуются от Еуэгегг. ОЬ)есщ каким образом привести их обратно к конкретным типам, чтобы обратиться к их свойствам' ? Можно попытаться применить рефлексию, но это потребует выполнения такого объема работы, что выигрыш от использования анонимных типов будет сведен на нет.
Аналогично, если необходимо передавать экземпляры анонимных типов из функций через выходные параметры или с помощью оператора гетцгп, то их следует передавать в виде ссылок на Еуэгегл. ОЬ)есщ таким образом, избавляя переменные от полезной информации о типе. Если требуется передавать экземпляры из метода, то вместо анонимного типа следует применять явно определенный тип, такой как Сопчепгьопа1Епр1оуее1пГо.
Узнав обо всех этих ограничениях, касающихся анонимных типов, может возникнуть вопрос, а в чем вообще их польза, за исключением редких случаев внутри локального контекста? Однако выясняется. что они чрезвычайно полезны при использовании с операциями проекций в языке ЬПЩ, что и будет показано в главе 16. Инициализаторы объектов В С№ предусмотрено сокращение, которое можно использовать при инициализации новых экземпляров объектов. Наверняка вам часто приходилось писать код, подобный приведенному ниже: Еьр1оуее оече1орег = пеи Етр1оуее О с1ече1орег.иаяе = кугео В1аге"г сгече1орег.огг1сеЬосаг1оп = "В1"; 4 Ннициализаторы проекции очень удобны, когда используются вместе с Ь1ХДг, о чем будет рассказано в главе 16.
106 Глава 4 Сразу после создания экземпляра Епр1оуее немедленно выполняется инициализация доступных свойств экземпляра. Не правда ли, было бы здорово, если бы можно было делать все это в одном операторег Разумеется, всегда можно создать специализированную перегрузку конструктора, принимающего параметры для инициализации нового экземпляра. Однако бывают случаи, когда удобнее этого не делать. Новый синтаксис инициализатора объекта показан ниже: ия1пс Яуягеп; риЬ11с с1ввв Епр1оуее ( риЫЕс виг1пс капе ( оес) вес; ) риЫЕс вгг1пс ОЕЕЕсеьосвеаоп ( сес; вес; ) ) риЫЕс с1ввв 1пЕЕЕхвпр1е ( яиас1с чоти паап() ( Еяр1оуеа Яечв1орах пе» Вяр1оуаа ( Ваяв ** "ухаб В1азе", ОЕЕ1свъосас1оп "В1" ): Обратите внимание на то, как инициализируется экземпляр сече1орег в методе Мвтп. "За кулисами" компилятор генерирует тот же код, какой получился бы в случае, если бы свойства иницнализировались вручную после создания экземпляра Еяр1оуее.
Поэтому такая техника работает только в случае доступности свойств — в данном случае нане и ОЕЕЕсеьосасаоп — в точке инициализации. Иницивлизаторы объектов можно даже вкладывать друг в друга, как показано в следующем примере: ив1пс Яуягелп риЬ11с с1вяя Епр1оуее ( риЬ11с вгг1пс Нэпе ( СЕЫ яею ) риЫЕс вггтпо ОЕЕЕсеьосаиаоп ( дегл яег; ) ) риЬ11с с1аяя Ееагигеоечрвтг ( риЬ11с Епр1оуее Рече1орег ( дегп яес; ) риЬ11с Епр1оуее ОвЕпдтпеег ( сег; вег; ) риЫЕс с1вяв тп1СЕхвпр1е ( вгвс1с чо1с Мвтп() ( Раасихевачваах ара11СЬас)ввхтаап = пв» Раасихввачаа1х ( Пвча1орех = па» Вар1оуев ( Ваяв "Епеб В1аае", ОЕЕасвт осасаоп "В1" Классы, структуры и объекты 107 ()акпд1паег паы Енр1оуае ( Базе "Наг1за Возва", ОЕЕ1саьосас1оп = тд42" ) ) ) Обратите внимание, что два свойства вре11СЬес)тегтеан инициализируются с использованием нового синтаксиса.
Каждый экземпляр Епр1оуее, присваиваемый свойствам, сэм инициализируется посредством объектного инициализатора. И, наконец, посмотрите, как выглядит еще более краткий способ инициализации объектов, позволяющий сократить объем клавишного ввода за счет скрытого усложнения: ивтпд Яувсеа; риЫТс с1авв Епр1оуее ( риЬ11с яггтпд Базе ( дест вег; ) риЫТс зггтпд ОТТТсеьосастсп ( дегт вест ) ) риЫТс с1авв РеагигепечРа(г ( рг1чаве Жвр1оуав к(ече1орег в пеы Еар1оува() т рг1чаев Еар1оуее дакпд1пвег пеы Енр1оуее(); риЫТс Епр1суее Оече1орег ( дег ( гесигп Оече1орегт ) вес ( т(ече1орег = ча1иет ) ) риЬ11с Еар1оуее ЯаЕпдтпеег ( дег ( гесигп даЕпдтпеегт ) яег ( даЕпд1пеег = ча1иет ) ) ) риЫТс с1авя 1п1ГЕхаар1е ( вгастс чогб Ма1п () ( Реазигепечра1г ера11СЬвс)кегТеаа в пеы РеагигепечРааг ( Оеча1орег = ( Базе = "Раек( В1аве", ОШ.саьосагаоп = "В1" Яакпд1пваг в ( Бале = "Иаг1ва Вовва", ОЕЕ1свьосаз1оп = "142" ) ) ) Как видите, здесь появилась возможность опустить выражения пеи при инициализации свойств Оече1орег и ()акпд1пеег объекта зре11СЬес)тегтеалт.














