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

Chars  -->  unknown

Length  -->  51

Заметьте, что любой индексатор трактуется .NET Framework, как индексируемое свойство.

В нашем случае индексатор не выводит значения, так как индекс не задан. Теперь применим расширение Dump к анонимному объекту song.

Console.WriteLine("\nDump object:");

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

song.Dump();

Вывод, производимый Dump, очевиден.

Artist  -->  Ray Charles

Song  -->  Alexander's Ragtime Band

Можно-ли применить метод Show для объекта song?

Вторая версия метода Dump(this IList) применима только к коллекциям объектов. Проверим ее с помощью массива анонимных объектов и заодно посмотрим, как работает расширение IsIn для объекта song.

Console.WriteLine("\nDump array of objects:");

var songs = new[]

{

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

song,

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

};

songs.Dump();

Console.WriteLine ("song.IsIn(songs): " + song.IsIn(songs));

Добавьте в класс Extender следующий метод и убедитесь, что класс String пополнился методом LengthOrNull.

public static int? LengthOrNull (this string s) { if (s == null) return null; else return s.Length; }

Для проверки этого факта можно выполнить такой фрагмент.

string s = null;

int? len = s.LengthOrNull();

Console.WriteLine("String: '{0}' has length: {1}", s, len ?? 0);

s = "LengthNull extends class String";

len = s.LengthOrNull();

Console.WriteLine("String: '{0}' has length: {1}", s, len ?? 0);

Поясните логику использования модификатора ? и операции ??.

Extension-методы класса Enumerable

В предыдущем параграфе мы показали, как добавить метод, расширяющий возможности какого-либо типа. В классах пространства имен System.Linq существует множество таких методов (extension methods). Их используют при работе с последовательностями произвольных типов. Напомним, что последовательностью называется любая коллекция, реализующая интерфейс IEnumerable<T>.

Заметим, что все типы коллекций, с которыми вы встречались до сих пор: Array, ArrayList, Stack, Queue, Hashtable, SortedList реализуют интерфейс IEnumerable. Все generic-коллекции: Stack<T>, Queue<T>, List<T>, LinkedList<T>, Dictionary <TKey, TValue>, а также базовый класс Collection<T>, служащий для создания ваших собственных generic-коллекций, реализуют интерфейс IEnumerable<T>. Все указанные коллекции подходят под определение последовательности.

Большинство запросов LINQ реализуется с помощью статических extension-методов, которые определены в статическом классе System.Linq.Enumerable. В качестве первого (this) параметра все эти методы имеют переменную типа IEnummerable<T>, что призвано расширить функциональность последовательностей объектов произвольных типов.

Анонимные объекты, или проецирование на произвольные структуры

Анонимные типы — это сокращенная форма инициализатора объекта, позволяющая пропустить описание типа. Рассмотрим, например,  инициализатор массива customers.

var customers = new[]

{

new { FName="Arthur", LName="Conan Doyle", Phone="323-3232", City="Edinburgh", Addr="Stonyhurst 32" },

new { FName="Sherlock", LName="Holmes", Phone="555-5555", City="London", Addr="Baker st 221B" },

new { FName="John", LName="Watson", Phone="555-5555", City="London", Addr="Baker st 221B" }

};

Составим запрос к массиву customers.

var query = customers.Select(c => new { c.LName, c.Addr });

Результат запроса может быть выведен в консольное окно таким образом.

foreach (var item in query)

Console.WriteLine(item);

Обратите внимание на часть строки LINQ-запроса:

. . . new { c.LName, c.Addr };