Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 123
Текст из файла (страница 123)
Как подразумевает само название, анонимный тип представляет собой класс, не имеющий имени. Его основное назначение состоит в создании объекта, возвращаемого оператором зе1есс. Результатом запроса нередко оказывается последовательность объектов, которые составляются из членов, полученных из двух или более источников данных (как, например, в операторе 1оъп), или же включают в себя подмножество членов из одного источника данных. Но в любом случае тип возвращаемого объекта зачастую требуется только в самом запросе и не используется в остальной части программы.
Благодаря аномиммому типу в подобных случаях отпадает необходимость объявлять класс, который предназначается только для хранения результата запроса, Анонимный тип объявляется с помощью следующей об(цей формьс печ ( нмч Л = значение л, нмн В = значение В, ... ) где имема обозначают идентификаторы, которые преобразуются в свойства, доступные только для чтения и инициализируемые значениями, как в приведенном ниже примере. печ ( Соопс = 10, Мах = 100, Мгп = 0 ) В данном примере создается класс с тремя открытыми только для чтения свойствами: сопок, Мах и Муп,которым присваиваются значения 10, 100 и 0 соответственно.
К этим свойствам можно обращаться по имени из другого кода. Следует заметить, что в анонимном типе используются инициализаторы объектов для установки их полей и свойств в исходное состояние. Как пояснялось в главе 8, инициализаторы объектов обеспечивают инициализацию объекта без явного вызова конструктора. Именно это и требуется для анонимных типов, поскольку явный вызов конструктора для них невозможен.
(Напомним, что у конструкторов такое же имя, как и у их класса. Но у анонимного класса нет имени, а значит, и нет возможности вызвать его конструктор.) Итак, у анонимного типа нет имени, и поэтому для обращения к нему приходится использовать неявно типизированную переменную. Это дает компилятору возможность вывести надлежащий тип. В приведенном ниже примере объявляется переменная вуОЬ, которой присваивается ссылка на объект, создаваемый в выражении анониммого типа. чаг вуОЬ = печ ( Сопок = 10, Мах = 100, Мъп = 0 ) Это означает, что следующие операторы считаются вполне допустимыми; Сопао1е.игъкевьпе("Счет равен " е вуОЬ.Сопок)) 11(1 <= вуоь.мах ьа 1 >= вуОЬ.м10) // Глава! 9. 1!))() ЕЗ9 Напомним, что при создании объекта анонимного типа указываемые идентификаторы становятся свойствами, открытыми только для чтения.
Поэтому их можно использовать в других частях кода, Термин анонимный тип не совсем оправдывает свое название, Ведь тип оказывается анонимным только для программирующего, но не для компилятора, который присваивает ему внутреннее имя. Следовательно, анонимные типы не нарушают принятые в С(( правила строгого контроля типов. Для того чтобы стало более понятным особое значение анонимных типов, рассмотрим переделанную версию программы из предыдущего раздела, посвященного оператору ] суп. Напомним, что в этой программе класс Тевр требовался для инкапсуляции результата, возвращаемого оператором дохл.
Благодаря применению анонимного типа необходимость в этом классе-заполнителе отпадает, а исходный код программы становится менее громоздким. Результат выполнения программы при этом не меняется. // использовать анонимный тип для усовершенствования // программы, демонстрирующей применение оператора зоьп. иягпд Яуяпевп ияьпд Яуяпев.вьп // Класс, связывапппий наименование товара с // его порядковым номером. с1аяя 1пев ( риЫьс ятг1пд Неве ( деш яеш ) риЬ11с ьпп 1певиивьег ( депп яеш ) риЫьс 1пев(япггпд и, 1пп 1пив) ( паве = и; 1певиивьег = ьпипи ) ) // Класс, связывающий наименование товара с // состоянием его запасов на складе. с1аяя 1пзтосКЯСапия ( риЫьс ьпС 1певиивьег ( деш яепп ) риЫьс Ьоо1 1пЯСосх ( деп) яеш риЫьс 1пЯСоскэпапия(ьпп и, Ьоо1 Ы ( 1певиивьег = пп 1пЯтосх = Ь; ) ) с1аяя апоптуреэево ( ятат1с чо1й Маьп() '( 1пев(! 1певя = ( пен 1пев(пкусачки", 1424), пен тпев("Тиски", 7892), пен 1сев("Молоток", 8534), пен 1пев("Пила", 8411) ): 1пЯСосКЯСапия(] ятатияъьяп = ( 640 Часть ), язык Сз пем ХпЯГосХЯГасцз(1424, Ггце), пен ХпзсосхЯГасцз(7892, Еа1зе), пен Хпзсосхзсасцз(8534, Ггце), пен Хпзсоскзсасцз(6411, Ггце) )' // Сформировать запрос, объединяющий объекты // классов 1сещ и ХпЯГоскзсасцз для составления // списка наименований товаров и ик наличия // на складе.
// Теперь для этой цели используется анонимный тип. наг ХпЯГоскъгзс = Ггощ гсещ 1п гсещз ]ого епсгу гп зсасцзъвзс оп Хсещ.ХГещпцщЬег ейца1з епсгу.ХГещпцщЬег зе1есс пен ( Маме = гсещ.паще, Хпзсоск = епсгу.Хпзсоск ); сопзо1е.игггеьгпе("тозар1гналичие1п")7 // Выполнить запрос и вывести его результаты. Йогеасп(наг Г 1п 1пзсосхъгзг) Сопзо1е.иггсеъгпе("(0) ХГ(1)", Г.каме, Г.Хпзсоск)) Обратите особое внимание на следующий оператор зе1есг: зе1есс пен ( Наще = гсещ.чаще, Хпзсоск = епсгу.ХпБГоск ): Он возвращает объект анонимного типа с двумя доступными только для чтения свойствами: Маме и 1ПБГосх. Этим свойствам присваиваются наименование товара и состояние его наличия на складе. Благодаря применению анонимного типа необходимость в упоминавшемся выше классе Тещр отпадает. Обратите также внимание на цикл гогеасЬ, в котором выполняется запрос.
Теперь переменная шага этого цикла объявляется с помощью ключевого слова чаг. Это необходимо потому, что у типа объекта, хранящегося в переменной 1ПБГосКЪХЯГ, нет имени. Данная ситуация послужила одной из причин, по которым в версии СФ 3.0 были внедрены неявно типизированные переменные, поскольку они нужны для поддержки аноним- НЫХ ТИПОВ. Предгде чем продолжить изложение, следует отметить еше один заслуживающий внимания аспект анонимных типов.
В некоторых случаях, включая и рассмотренный выше, синтаксис анонимного типа упрощается благодаря применению иниг4иализап)ора проекции. В данном случае просто указывается имя самого инициализатора. Это имя автоматически становится именем свойства. В качестве примера ниже приведен другой вариант оператора зе1есг из предыдущей программы. зе1есс пеи ( гсещ.пане, епсгу.гпзсосх ); В данном примере имена свойств остаются такими же, как и прежде, а компилятор автоматически "проецирует" идентификаторы Маме и ХПЯГосх, превращая их в свойства анонимного типа.
Этим свойствам присваиваются прежние значения, обозначаемые 1сещ. Маме и епегу. ХПБСосх соответственно. Глава!9. ОНО 641 Создание группового обьединения Как пояснялось ранее, оператор 1пго можно использовать вместе с оператором 9 охп для создания группового обьединения, образующего последовательность, в которой каждый результат состоит из элементов данных из первой последовательности и группы всех совпадающих элементов из второй последовательности. Примеры группового объединения не приводились выше потому, что в этом объединении нередко применяется анонимный тип. Но теперь, когда представлены анонимные типы, можно обратиться к простому примеру группового объединения. В приведенном ниже примере программы групповое объединение используется для составления списка, в котором различные транспортные средства (автомашины, суда и самолеты) организованы по общим для них категориям транспорта: наземного, морского, воздушного и речного.
В этой программе сначала создастся класс Тгапя роге, связывающий вид транспорта с его классификацией. Затем в методе Маъп () формируются две входные последовательности. Первая из них представляет собой массив символьных строк, содержащих названия общих категорий транспорта: наземного, морского, воздушного и речного, а вторая — массив объектов типа Тгапярогт, инкапсулирующих различные транспортные средства. Полученное в итоге групповое объединение используется для составления списка транспортных средств, организованных по соответствующим категориям.
// Продемонстрировать применение простого // группового объединения. цяхпд Зуясев; ця1пп Яуясев.ъгпсн // Этот класс связывает наименование вида транспорта, // например поезда, с общей классификацией транспорта: // наземного, морского, воздушного или речного. с1аяя Тгапярогг ( рць11с ягг1пд паве ( чес; яег; ) рцьгхс ясг1пд Нон ( Нес; яес; ) рць11с Тгапярогс(ягггпп и, ягггпп Ь) ( паве = и; Нон = (и ) с1аяя Пгоцрзоъпоево ( ясасхс чо1б Маьп() ( // Массив классификации видов транспорта.
ясгьпд[) Ггане1турея = ( "Воздушный", "Морской", "Наземный", "Речной", )' // Массив видов транспорта. Тгапярогс[] ггапяроггя = ( пен Тгапярогс("велосипед", "Наземный" ), 642 Часть ). Язык С» ПЕН ТГаоэрОГС(яазрОСтат", явсэдуШНЬПЗя), пен Тгапврогс("лодка", "Речной" ), ПЕН ТГалэрОГГ(ноаМОЛЕт", "ВОЗдуШНЫЙ" ), пен Тгапврогс("каноэ", "Речной" ), пен Тгапврогс("биплан", "Воздушный" ), пен Тгапврогс("автомашина", ЯНаэемный"), пен Тгапврогс("судно", "Морскойя), пеи Тгапврогс("поезд", "Наземный") // Сформировать запрос, в котором групповое // объединение используется для составления списка // видов транспорта по соответствующим категориям.
чаг ЬуНон = Тгош Ьон Тп Ггаче1Турев )озп Сгапв Тп Сгапвроггв оп Ьон ецпа1в Ггапз.Нои ьпсо 1вс ве1есг пен ( Нон = Ьон, Т1»вс = 1вс ); // Выполнить запрос и вывести его результаты. Тогеасп(чаг Г 1п ЬуНон) ( Сопво1е.ыг1сев»пе(яК категории <(0) транспорт> относится:", С.Нон)т Тогеасп(чаг ш 1п С.Т1»вс) Сопво1е.нгзсесзпе(" " + ш.наше)т сопво1е.нг1геьзпе()т ) ) ) Ниже приведен результат выполнения этой программы.
К категории <Воздушный транспорт> относится: аэростат самолет биплан К категории <Морской транспорт> относится: судно К категории <Наземный транспорт> относится: велосипед автомашина поезд К категории <Речной транспорт> относится: лодка каноэ Главной частью данной программы, безусловно, является следующий запрос: чаг ЬуНон = Тгош Ьон Тп Ггаче1Турез »озп Ггапз 1п Ггапвроггв оп Ьон еяпа1в Ггапв.Нон Тпсо 1вс ве1есс пен ( Нон = Ьон, Т11вс = 1вс ); Глава 19.