Рассмотренный здесь пример применения оператора join довольно прост. Тем не менее этот оператор поддерживает и более сложные операции с источниками дан ных. Например, используя совместно операторы into и join, можно создать групповое объединение, чтобы получить результат, состоящий из первой последовательности и группы всех совпадающих элементов из второй последовательности. (Соответствую щий пример будет приведен далее в этой главе.) Как правило, время и усилия, затра ченные на полное освоение оператора join, окупаются сторицей, поскольку он дает возможность распознавать данные во время выполнения программы. Это очень ценная возможность. Но она становится еще ценнее, если используются анонимные типы, о которых речь пойдет в следующем разделе. Анонимные типы
В C# предоставляется средство, называемое анонимным типом и связанное непо средственно с LINQ. Как подразумевает само название, анонимный тип представляет собой класс, не имеющий имени. Его основное назначение состоит в создании объек та, возвращаемого оператором select. Результатом запроса нередко оказывается по следовательность объектов, которые составляются из членов, полученных из двух или более источников данных (как, например, в операторе join), или же включают в себя подмножество членов из одного источника данных. Но в любом случае тип возвращае мого объекта зачастую требуется только в самом запросе и не используется в остальной части программы. Благодаря анонимному типу в подобных случаях отпадает необхо димость объявлять класс, который предназначается только для хранения результата запроса.
Анонимный тип объявляется с помощью следующей общей формы: new { имя_А = значение_А, имя_В = значение_В, ... }
где имена обозначают идентификаторы, которые преобразуются в свойства, доступ ные только для чтения и инициализируемые значениями, как в приведенном ниже примере. new { Count = 10, Max = 100, Min = 0 }
В данном примере создается класс с тремя открытыми только для чтения свойства ми: Count, Мах и Min, которым присваиваются значения 10, 100 и 0 соответственно. К этим свойствам можно обращаться по имени из другого кода. Следует заметить, что в анонимном типе используются инициализаторы объектов для установки их полей и свойств в исходное состояние. Как пояснялось в главе 8, инициализаторы объектов обеспечивают инициализацию объекта без явного вызова конструктора. Именно это и требуется для анонимных типов, поскольку явный вызов конструктора для них невоз можен. (Напомним, что у конструкторов такое же имя, как и у их класса. Но у аноним ного класса нет имени, а значит, и нет возможности вызвать его конструктор.) Итак, у анонимного типа нет имени, и поэтому для обращения к нему приходится использовать неявно типизированную переменную. Это дает компилятору возмож ность вывести надлежащий тип. В приведенном ниже примере объявляется перемен ная myOb, которой присваивается ссылка на объект, создаваемый в выражении аноним ного типа. var myOb = new { Count = 10, Max = 100, Min = 0 }
Это означает, что следующие операторы считаются вполне допустимыми. Console.WriteLine("Счет равен " + myOb.Count); if(i <= myOb.Max && i >= myOb.Min) // ...
Напомним, что при создании объекта анонимного типа указываемые идентифи каторы становятся свойствами, открытыми только для чтения. Поэтому их можно ис пользовать в других частях кода.
Термин анонимный тип не совсем оправдывает свое название. Ведь тип оказывается анонимным только для программирующего, но не для компилятора, который присва ивает ему внутреннее имя. Следовательно, анонимные типы не нарушают принятые в C# правила строгого контроля типов.