LINQ в C#

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#. Данных знаний должно хватить для того, что использовать этот механизм на практике.

На связи был Алексей Гулынин, оставляйте свои комментарии, увидимся в следующих статьях.


Комментарии:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *