LINQ в C#

LINQ (Language Integrated Query) в C# — это простой и удобный интегрированный язык запросов к источнику данных. Причем в качестве источника данных LINQ могут выступать, как обычные массивы или списки, так и XML-документы, наборы данных DataSet и т.д. Запросы в LINQ очень сильно напоминают запросы в SQL. В этой части мы рассмотрим основные моменты работы с LINQ в C# и научимся использовать основные возможности LINQ при работе с наборами данных,такими как массив или список.

Архитектура

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

В LINQ для каждого источника данных (базы данных, XML-документа, объекта в памяти и т.д.) используются свои поставщики LINQ или, как их ещё называют, провайдеры LINQ.

Провайдеры LINQ — это программные компоненты, позволяющие выполнять запросы к определённому источнику данных с использованием синтаксиса LINQ в .NET. То цель провайдера LINQ — это преобразовать запрос LINQ в запрос, понятный источнику данных.

Можно выделить следующие основные провайдеры LINQ:

  • LINQ to Objects — работа с массивами и коллекциями в памяти
  • LINQ to Entities работа с различными базами данных, с использованием технологии Entity Framework
  • LINQ to XML — работа с файлами XML
  • LINQ to DataSetработа с объектами DataSet
  • Parallel LINQ (PLINQ) выполнение параллельных запросов LINQ.

В общих чертах, работу LINQ можно представить следующим образом:

LINQ в C#

 

Примеры использования LINQ в C#

Выбор из массива строк с использованием LINQ

Чтобы получить возможность работать с LINQ, в проекте необходимо подключить пространство имен System.Linq. Для того, чтобы разобраться с тем,что из себя представляет LINQ и как его использовать в своих проектах C# рассмотрим решение такой простой задачи: необходимо выбрать из массива строк все строки, длина которых больше пяти символов. Без использования LINQ мы бы написали примерно такой код:

string[] strings = { "мир", "Привет", "Строка", "C#", "LINQ"};
List<string> result = new List<string>();
foreach (string s in strings)
{
    if (s.Length > 5)
    {
        result.Add(s);
    }
}
foreach (string s in result)
    Console.WriteLine(s);

C LINQ этот код можно сделать короче и выразительнее:

var res = from s in strings
          where s.Length > 5
          select s;
           
foreach (string s in res)
{
    Console.WriteLine(s);
}

Как можно видеть, синтаксис запроса в LINQ очень сильно похож на SQL, хотя и имеет некоторые различия. При этом, наиболее простой запрос в LINQ выглядит следующим образом:

from переменная in набор_объектов
select переменная;

Если переводить запрос LINQ на обычный язык, но на нашем примере получится следующее:

from s in strings

«все элементы s из набора strings»

where s.Length > 5

«у которых длина более 5»

select s

«поместить в res«.

Здесь в примере мы использовали неявно типизированную переменную (res), хотя, могли бы использовать и явный тип. Так как в качестве источника данных В качестве источника  данных для LINQ может выступать любой объект, реализующий интерфейс IEnumerable, то переписать пример мы могли бы так:

IEnumerable<string> res = from s in strings
                    where s.Length > 5
                    select s;

Сортировка массива с использованием LINQ

Ещё один показательный пример — использование LINQ для сортировки данных, например, массива чисел. В разделе «Алгоритмы» представлено несколько алгоритмов, реализующих сортировку массива чисел. Например, рассмотрим код, реализующий сортировку выбором:

//intArray - это массив целых чисел
int indx; //переменная для хранения индекса минимального элемента массива
for (int i = 0; i < intArray.Length; i++) //проходим по массиву с начала и до конца
{
    indx = i; //считаем, что минимальный элемент имеет текущий индекс 
    for (int j = i; j < intArray.Length; j++) //ищем минимальный элемент в неотсортированной части
    {
        if (intArray[j] < intArray[indx])  
        {
            indx = j; //нашли в массиве число меньше, чем intArray[indx] - запоминаем его индекс в массиве
        }
    }
    if (intArray[indx] == intArray[i]) //если минимальный элемент равен текущему значению - ничего не меняем
        continue;
    //меняем местами минимальный элемент и первый в неотсортированной части
    int temp = intArray[i]; //временная переменная, чтобы не потерять значение intArray[i]
    intArray[i] = intArray[indx];
    intArray[indx] = temp;
}

Это самый простой метод сортировки, однако, используя LINQ мы можем отсортировать массив буквально в одну строку:

int[] numbers = { 0, 100, 999, 345, -100, 1, 0, 9, 7, 6, 5, 4, 3, 2, 1, 67, 88 };
var sort = from i in numbers orderby i select i;

массив будет отсортирован в порядке возрастания.

Аналогичным образом мы можем работать с любыми наборами данных, главное, чтобы в качестве набора выступал объект, реализующий интерфейс IEnumerable. Кроме SQL-подобного стиля LINQ также предоставляет нам в распоряжение такую возможность, как использование методов расширения, определенных для интерфейса IEnumerable.

Методы расширения LINQ

Когда вы подключаете в проект пространство имен System.Linq, то все объекты, реализующие интерфейс IEnumerable, автоматически «обрастают» методами расширения LINQ. По сути, методы расширения LINQ позволяют избавиться от SQL-подобного стиля в коде вашего проекта. Вот, например, как бы выглядел пример, представленный выше, если бы мы использовали методы расширения:

int[] numbers = { 0, 100, 999, 345, -100, 1, 0, 9, 7, 6, 5, 4, 3, 2, 1, 67, 88 };
var sort = numbers.OrderBy(t => t);
foreach (int t in sort)
{
    Console.Write($"{t} ");
}

В качестве параметров, методы расширения принимаю обычно делегат или лямбда-выражение. Также, используя методы расширения мы можем расширить варианты использования LINQ, например, мы можем отфильтровать массив строк и вывести количество слов в выборке, используя вот такую последовательность методов расшения:

 string[] strings = { "мир", "Привет", "Строка", "C#", "LINQ"};
 int count = strings.Where(s => s.Length > 5).Count();
 Console.WriteLine($"В итоговой выборке {count} слов");

Наиболее часто используемые методы расширения LINQ представлены ниже:

Об этих методах расширения LINQ более подробно в следующих статьях.

Итого

Использование возможностей LINQ в C# позволяет сделать ваш код более выразительным (понятным) для чтения и, одновременно, более лаконичным. В своих проектах вы можете использовать LINQ в SQL-стиле (что встречается довольно редко) или же использовать методы расширения, которые во многом повторяют операции выполняемые при SQL-подобном использовании LINQ, но и, при этом, упрощают использование LINQ, например, позволяя вычислять значения элементарных математических операций — подсчитывать средние значения, определять количество элементов выборки и так далее.

Подписаться
Уведомить о
guest
0 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии