Секреты LINQ. Автогенерируемые свойства. Инициализаторы объектов и коллекций, страница 9

IEnumerable<T> — интерфейс, который реализован почти всеми коллекциями. Более точно: интерфейс реализован классами, поддерживающими эти коллекции. Правила игры, описываемые этим интерфейсом, выполняют все массивы, так как массивы поддержаны abstract-классом Array, который реализует IEnumerable.

Рекурсивное определение: IEnumerable<T> описывает последовательность объектов типа T, а последовательность обозначает все коллекции, работающие по правилам IEnumerable<T>.

С учетом сказанного оператор var where = words.Where(c => c == "Where"); можно переписать в более "пространной" нотации.

Func<string, bool> func = c => c == "Where";  // Создание анонимного делегата с помощью λ-выражения

IEnumerable<string> where = words.Where(func);   // Использование делегата (многократный вызов)

Метод Where является примером применения новой синтаксической конструкции языка C#, называемой extension method (расширяющий метод). Мы рассмотрим расширяющие методы ниже.

Необходимость использования анонимных типов

В рассмотренных примерах мы показали, как вычислить точный тип var-объекта и заменить анонимный описатель var его точным значением. Но бывают случаи, когда сделать это невозможно. Покажем, как создать анонимный объект, тип которого вычисляется компилятором, и отсутствует возможность замены его каким-то конкретным описанием.

var song = new { Artist = "Ray Charles", Song = "Alexander's Ragtime Band" };

Здесь объявлен анонимный тип, который содержит два именованных (не анонимных) свойства Artist и Song. Имя же самого (вновь созданного компилятором) типа недоступно на стадии разработки кода. Так как тип объекта song нам не известен, то описатель var нельзя заменить чем-либо другим.

Отладчик сообщит нам, что тип объекта song — это <Anonymous Type>, но этот описатель не соответствует какому-либо типу библиотеки .NET, он передает лишь семантику использования объекта. Заменить var на <Anonymous Type> не удастся — компилятор его не примет.

Отметьте, что значения свойств Artist и Song можно только читать (изменять нельзя). Интересно то, что, не зная типа объектов, мы можем создать типизированный массив, или любую другую коллекцию этих объектов и спокойно работать с нею.

var songs = new[]

{

new { Artist = "Low Rowles", Song = "Cheek to cheek" },

song,

new { Artist = "Frank Sinatra", Song = "September In the Rain" }

};

Аксиома. Все массивы, кроме object[], являются типизироваными.

С помощью следующего кода убедитесь в том, что метод ToString() отлично обслуживает анонимные объекты.

foreach (var item in songs)

Console.WriteLine(item);

Обязательно выполните этот фрагмент в рамках проекта студии и проанализируйте его вывод.

{ Artist = Low Rowles, Song = Cheek to cheek }

{ Artist = Ray Charles, Song = Alexander's Ragtime Band }

{ Artist = Frank Sinatra, Song = September In the Rain }

Анонимные типы предоставляют удобный способ инкапсуляции множества свойств в рамках анонимного объекта. Формат вывода анонимных объектов очень похож на формат JSON (Java Scrip Object Notation), который часто используется при передаче даных по каналам RSS. Аббревиатура RSS (Really Simple Syndication) обозначает формат XML-документов, используемый Web-сайтами для публикации часто обновляемых данных, таких как: заголовки новостей (news headlines), или ленты посланий (blog posts).

Оператор yield

Контекстное ключевое слово yield [jild] действует как оператор, создающий итерационный блок, который позволяет вычислять выражение и сохранять его в перечислимом объекте. Последний можно использовать по мере надобности (сразу или потом). Рассмотрим код.

static void Main()

{

string[] words = { "class", "const", "continue", "decimal" };

IEnumerable<string> query = GetWords (words);

foreach (string w in query)

Console.WriteLine (w);

}