- •А.А. Волосевич
- •Содержание
- •1. Работа с числами
- •2. Представление даты и времени
- •3. Работа со строками и текстом
- •4. Преобразование информации
- •5. Сравнение для выяснения равенства
- •6. Сравнение для выяснения порядка
- •7. Жизненный цикл объектов
- •7.1. Алгоритм сборки мусора
- •7.2. Финализаторы и интерфейс iDisposable
- •7.3. Слабые ссылки
- •8. Перечислители и итераторы
- •9. Стандартные интерфейсы коллекций
- •10. Массивы и класс System.Array
- •11. Типы для работы с коллекциями-списками
- •12. Типы для работы с коллекциями-множествами
- •13. Типы для работы с коллекциями-словарями
- •14. Типы для создания пользовательских коллекций
- •15. Технология linq to Objects
- •1. Оператор условия Where().
- •2. Операторы проекций.
- •3. Операторы упорядочивания.
- •4. Оператор группировки GroupBy().
- •5. Операторы соединения.
- •6. Операторы работы с множествами.
- •7. Операторы агрегирования.
- •8. Операторы генерирования.
- •9. Операторы кванторов и сравнения.
- •10. Операторы разбиения.
- •11. Операторы элемента.
- •12. Операторы преобразования.
- •16. Работа с объектами файловой системы
- •17. Ввод и вывод информации
- •17.1. Потоки данных и декораторы потоков
- •2. Классы для работы с потоками, связанными с хранилищами.
- •3. Декораторы потоков.
- •4. Адаптеры потоков.
- •17.2. Адаптеры потоков
- •18. Основы xml
- •19. Технология linq to xml
- •20. Дополнительные возможности обработки xml
- •21. Сериализация времени выполнения
- •22. Контракты данных и xml-сериализация
- •23. Состав и взаимодействие сборок
- •24. Метаданные и получение информации о типах
- •25. Позднее связывание и кодогенерация
- •26. Атрибуты
- •27. Динамическое связывание
- •28. Файлы конфигурации
- •29. Диагностика и мониторинг
- •30. Процессы и домены
- •31. Основы многопоточного программирования
- •32. Синхронизация потоков
- •32.1. Критические секции
- •32.2. Синхронизация на основе подачи сигналов
- •32.3. Неблокирующие средства синхронизации
- •32.4. Разделение данных между потоками
- •33. Библиотека параллельных задач
- •33.1. Параллелизм на уровне задач
- •33.2. Параллелизм при императивной обработке данных
- •33.3. Параллелизм при декларативной обработке данных
- •33.4. Обработка исключений и отмена выполнения задач
- •33.5. Коллекции, поддерживающие параллелизм
- •34. Асинхронный вызов методов
- •Литература
15. Технология linq to Objects
Платформа .NET версии 3.5 представила новую технологию работы с коллекциями – Language Integrated Query (LINQ). По типу обрабатываемой информации LINQ делится на LINQ to Objects – библиотеки для обработки коллекций объектов в памяти, LINQ to SQL – библиотеки для работы с базами данных, LINQ to XML предназначена для обработки XML-информации. В данном параграфе акцент сделан на LINQ to Objects.
Технически, LINQ to Objects – это набор классов, содержащих типичные методы обработки коллекций: поиск данных, сортировка, фильтрация. Ядром LINQ to Objects является статический класс Enumerable, размещённый в пространстве имён System.Linq1 . Этот класс содержит набор методов расширения интерфейса IEnumerable<T>, которые в дальнейшем будут называться операторами LINQ. Для удобства дальнейшего изложения используем стандартное деление операторов LINQ на группы в зависимости от выполняемых действий:
1. Оператор условия Where (отложенные вычисления).
2. Операторы проекций (отложенные вычисления).
3. Операторы упорядочивания (отложенные вычисления).
4. Оператор группировки GroupBy (отложенные вычисления).
5. Операторы соединения (отложенные вычисления).
6. Операторы работы с множествами (отложенные вычисления).
7. Операторы агрегирования.
8. Операторы генерирования (отложенные вычисления).
9. Операторы кванторов и сравнения.
10. Операторы разбиения (отложенные вычисления).
11. Операторы элемента.
12. Операторы преобразования.
В примерах параграфа будут использоваться либо коллекции примитивных типов, либо коллекция gr объектов класса Student:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public IEnumerable<int> Marks { get; set; }
}
var gr = new List<Student>{
new Student {Name = "Smirnov", Age = 18, Marks = new[] {10, 8, 9}},
new Student {Name = "Ivanova", Age = 20, Marks = new[] {5, 6, 9}},
new Student {Name = "Kuznetsov", Age = 18, Marks = new[] {7, 7, 4}},
new Student {Name = "Sokolov", Age = 20, Marks = new[] {7, 8, 8}},
new Student {Name = "Lebedeva", Age = 20, Marks = new[] {9, 9, 9}}
};
1. Оператор условия Where().
Оператор производит фильтрацию коллекции, основываясь на аргументе-предикате. Сигнатуры оператора1:
IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, bool> predicate);
IEnumerable<T> Where<T>(this IEnumerable<T> source,
Func<T, int, bool> predicate);
Второй вариант оператора Where() позволяет передать аргументу-предикату индекс элемента в коллекции (заметим, что многие другие операторы имеют перегруженную версию, устроенную по такому же принципу).
Примеры использования Where():
var list = new List<int> {1, 3, -1, -4, 7};
var r1 = list.Where(x => x < 0);
var r2 = gr.Where(student => student.Age > 19);
var r3 = gr.Where((student, pos) => student.Age > 19 && pos < 3);
2. Операторы проекций.
Операторы проекций применяются для выборки информации, при этом они могут изменять тип элементов итоговой коллекции. Основным оператором проекции является Select():
IEnumerable<S> Select<T, S>(this IEnumerable<T> source,
Func<T, S> selector);
Оператор SelectMany() может применяться, если результатом проекции является набор данных. В этом случае оператор соединяет все элементы набора в одну коллекцию.
IEnumerable<S> SelectMany<T, S>(this IEnumerable<T>source,
Func<T, IEnumerable<S>> selector);
Примеры использования операторов проекций:
var r1 = gr.Select(student => student.Name);
var r2 = gr.Select(student => new {student.Name, student.Age});
var r3 = gr.SelectMany(student => student.Marks);
Коллекция r1 будет содержать имена студентов. Коллекция r2 состоит из объектов анонимного типа с полями Name и Age. Коллекция r3 – это все оценки студентов (15 элементов типа int).