Кортеж (англ. tuple) — это тип значений, который позволяет сгруппировать несколько элементов данных в упрощенную структуру. Кортежи впервые появились в C# 7.0 и, на данный момент, находят свое применение в различных ситуациях, когда использование, например, классов избыточно, но при этом, необходимо оформить ряд данных в единую структуру.
Синтаксис кортежей
Для определения кортежа в коде мы можем использовать следующую конструкцию:
(тип_1, тип_2, ..., тип_n) Имя_кортежа
То есть мы перечисляем внутри круглых скобок типы данных, которые будут хранится в кортеже. Например, определим следующий кортеж:
(int, int) tuple = (10, 1);
Теперь мы можем обратиться к элементам кортежа используя следующий синтаксис:
имя_кортежа.ItemПорядковый_номер
где имя_кортежа
— это имя переменной; Порядковый_номер
— номер элемента в кортеже, начиная с 1. Перечислим элементы кортежа:
(int, int) tuple = (10, 1); Console.WriteLine(tuple.Item1); //10 Console.WriteLine(tuple.Item2); //1
Также мы можем задавать имена полей кортежа, например:
(int number, string text, double sum) namedTuple; namedTuple.number = 5; namedTuple.text = "Hello, world!"; namedTuple.sum = 10.0;
В этом примере мы объявили кортеж с тремя именованными полями — number
, text
и sum
, причем, каждое поле имеет свой тип данных — int
, string
и double
. И теперь мы можем обращаться к полям кортежа по их именам или же продолжить стандартное обращение к полям, используя конструкцию в Item.
Деконструкция кортежей и присваивание
При необходимости, мы можем разобрать кортеж на отдельные переменные. Чтобы произвести деконструкцию кортежа в отдельные переменные необходимо использовать оператор присваивания =
. Рассмотрим следующий пример:
(int number, string text, double sum) = (5, "Строка", 10.1); Console.WriteLine(number); Console.WriteLine(text); Console.WriteLine(sum);
В этом примере демонстрируется один из вариантов деконструкции кортежа в отдельные переменные. Другой пример:
var t2 = (15, "Привет", 0.1); var (a, b, c) = t2; Console.WriteLine(a);//15 Console.WriteLine(b);//Привет Console.WriteLine(c);//0.1
Здесь мы используем ключевое слово var
, указывая компилятору, что он должен сам вывести типы переменных.
Возможность использования оператора присваивания для двух кортежей позволяет нам использовать ещё одну замечательную возможность при работе с кортежами, а именно — обмен значений внутри кортежа. Например,
int a = 2; int b = 1; (a, b) = (b, a); Console.WriteLine((a, b));
Здесь мы меняем значения a
и b
местами, то есть в консоль будет выведено:
Применение кортежей
Кортежи в C# находят применение при разработке методов — кортеж может выступать и как параметр метода и как его результат. Например, если предполагается, что метод должен вернуть несколько значений, то в качестве типа результата можно определить кортеж:
Console.WriteLine(Sum(5,10)); (int a, int b, int c) Sum(int x, int y) { return (x, y, x + y); }
Здесь метод Sum()
возвращает кортеж, состоящий из трех полей типа int
. Результат в консоли:
Аналогичным образом кортеж может выступать и в качестве параметров метода:
Console.WriteLine(Calculate((5, 10, Operation.Add))); Console.WriteLine(Calculate((5, 10, Operation.Multiply))); Console.WriteLine(Calculate((5, 10, Operation.Divide))); (int a, int b, int c) Calculate((int x, int y, Operation operation) data) { var (x, y, operation) = data; switch (data.operation) { case Operation.Add: return (x, y, x + y); case Operation.Multiply: return (x, y, x * y); case Operation.Divide: return (x, y, x / y); default: return (x, y, x + y); } } enum Operation { Add, Multiply, Divide }
Здесь метод Calculate()
принимает в качестве параметра кортеж из трех полей и также возвращает кортеж. Чтобы произвести деконструкцию кортежа внутри метода мы использовали операцию присваивания. Если бы мы не выполнили эту операцию то, кд метода был бы немного длиннее — нам бы пришлось обращаться к полям кортежа по их именам, например, чтобы сложить два числа:
data.x + data.y
Опять же, в консоли мы увидим следующий вывод:
(5, 10, 50)
(5, 10, 0)
Итого
Кортежи — это компактный и лаконичный способ объединения различных данных в единую структуру. В отличие от классов, внутри кортежей нельзя объявлять свойства и методы и так далее, однако это и не требуется в том случае, если нам достаточно просто получить/передать единую структуру с различными данными.