LINQ в C#

Всем доброго времени суток. На связи Алексей Гулынин. В прошлой статье мы поговорили про индексирующее свойство в C#. В данной статье я бы хотел поговорить про технологию LINQ в C#. LINQ (Language Integrated Query) — интегрированный язык запросов. Те, кто работал с базами данных, наверняка использовали SQL (Structured Query Language), который позволяет выполнять запрос к базе: извлекать данные из неё, изменять их, удалять. Особенностью SQL является то, что это декларативный язык.
Постараюсь пояснить: на SQL мы не описываем алгоритм, мы описываем результат, который хотим получить. Это очень удобно для работы с большими источниками данных. Это хорошо, когда у нас есть сервер базы данных, но что делать если у нас данные находятся в памяти в виде коллекции или массива. Допустим, мы создаём коллекцию людей (их имя и количество лет). Коллекция будет типа "Dictionary". Затем из данной коллекции мы хотим получить имена людей, чей возраст больше определенного заданного числа и заодно отсортировать людей по имени.
Конечно, это можно сделать просто: описать определенный алгоритм с циклом, который пробегает по всей коллекции и сравнивает возраст человека с тем числом, которое мы задали. В случае успеха эти люди добавляются в какую-то временную коллекцию. В данном случае хочется использовать тот же подход, что и с SQL.
LINQ как раз и позволяет декларативно написать запрос к различным источникам данных (коллекции, массивы).
Давайте на примере разберем, как использовать этот механизм:
Dictionary<string,int> myDictionary = new Dictionary<string,int>(); myDictionary.Add("Александр", 25); myDictionary.Add("Петр", 35); myDictionary.Add("Иван", 20); myDictionary.Add("Семен", 15); myDictionary.Add("Андрей", 5); var result = // myDictionary.Keys - коллекция ключей, в нашем случае имён from string name in myDictionary.Keys // здесь по ключу получаем значение, т.е. возраст where myDictionary[name] > 18 // сортируем по имени (по ключу) orderby name select name; foreach (string name in result) Console.WriteLine(name); // Выйдет Александр, Иван, Петр
Поясню данный код. Сперва, я создаю коллекцию "Dictionary", в которую помещаю имя человека и его возраст (метод "Add"). "var result" — это переменная, в которой будет храниться результат нашего запроса. var обычно пишут, чтобы не задумываться о том, какой тип данных вернет LINQ-запрос.
Далее, как раз, начинается декларация того, что мы хотим получить. Очень сильно похоже на "SQL". Сразу обращу ваше внимание на то, что "select" ставится в конце. "name" — это имя, которое фактически будет использоваться, как переменная цикла.
Для того, чтобы код работал нужно подключить соответствующие пространства имён:
using System.Collections.Generic; using System.Linq;
Рассмотрим пример: необходимо получить имя самого младшего человека в коллекции.
var result2 = from string name in myDictionary.Keys orderby myDictionary[name] select name; string molodoi = result2.First<string>(); Console.WriteLine(molodoi); // выйдет Андрей
Для информации отмечу, что "LINQ" очень часто используется с "Entity Framework" для взаимодействия с объектной базой данных.
Реализуем какой-нибудь пример из жизни. Пусть имеется текстовый файл, в котором содержатся различные записи (1 строка — 1 запись). Необходимо получить список неуникальных записей, т.е. тех, которые повторяются. И эти повторяющиеся записи записать в отдельный файл.
try { string line = ""; // Создаём список, в котором будут храниться все имена из файла List<string> listNames = new List<string>(); // Данная конструкция используется для того, чтобы по окончанию работы с файлом // закрыть его. using (StreamReader sr = new StreamReader(@"C:\not_unique_names.txt", Encoding.Default)) { // Считываем файл построчно while ((line = sr.ReadLine()) != null) { // Добавляем каждую строку в наш список listNames listNames.Add(line.Trim()); } } // Находим список повторяющихся элементов // Вся мощь LINQ в одной строке // Хочу обратить внимание, что здесь мы уже используем методы // Это ещё один подход для написания запросов LINQ var uniqueListNames = listNames.GroupBy(v => v).Where(g => g.Count() > 1).Select(g => g.Key); // Записываем повторяющиеся элементы в файл // false - файл будет каждый раз перезаписываться using (StreamWriter sw = new StreamWriter(@"C:\repeted_names.txt", false, Encoding.Default)) { foreach (string li in uniqueListNames) { sw.WriteLine(li); } } Console.WriteLine("Нажмите клавишу для продолжения..."); Console.ReadLine(); } catch (Exception e) { Console.WriteLine("Во время выполнения кода произошла ошибка: \n" + e.Message); Console.ReadLine(); }
В данной статье вы узнали немного о том, как работать с LINQ в C#. Данных знаний должно хватить для того, что использовать этот механизм на практике.
На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.