Кортежи предоставляют удобный способ для работы с набором значений, который был добавлен в версии C# 7.0.
Кортеж представляет набор значений, заключенных в круглые скобки:
var tuple = (5, 10);
В данном случае определен кортеж tuple, который имеет два значения: 5 и 10. В дальнейшем мы можем обращаться к каждому из этих значений через поля с названиями:
Item[порядковый_номер_поля_в_кортеже]
Например:
var tuple = (5, 10); Console.WriteLine(tuple.Item1); // 5 Console.WriteLine(tuple.Item2); // 10 tuple.Item1 += 26; Console.WriteLine(tuple.Item1); // 31
В данном случае тип определяется неявно. Но мы также можем явным образом указать для переменной кортежа тип:
(int, int) tuple = (5, 10);
Так как кортеж содержит два числа, то в определении типа нам надо указать два числовых типа. Или другой пример определения кортежа:
(string, int, double) person = ("Tom", 25, 81.23);
Первый элемент кортежа в данном случае представляет строку, второй элемент - тип int, а третий - тип double.
Мы также можем дать названия полям кортежа:
var tuple = (count:5, sum:10); Console.WriteLine(tuple.count); // 5 Console.WriteLine(tuple.sum); // 10
Теперь чтобы обратиться к полям кортежа используются их имена, а не названия Item1 и Item2.
Мы даже можем выполнить декомпозицию кортежа на отдельные переменные:
var (name, age) = ("Tom", 23); Console.WriteLine(name); // Tom Console.WriteLine(age); // 23
Одной из задач, которую позволяет элегантно решить кортеж - это обмен значениями:
string main = "Java"; string second = "C#"; (main, second) = (second, main); Console.WriteLine(main); // C# Console.WriteLine(second); // Java
Что можно использовать, например, при простейшей сортировке массива:
int[] nums = { 54, 7, -41, 2, 4, 2, 89, 33, -5, 12 }; // сортировка for (int i = 0; i < nums.Length - 1; i++) { for (int j = i + 1; j < nums.Length; j++) { if (nums[i] > nums[j]) (nums[i], nums[j]) =(nums[j], nums[i]); } } // вывод Console.WriteLine("Вывод отсортированного массива"); for (int i = 0; i < nums.Length; i++) { Console.WriteLine(nums[i]); }
Кортежи могут выступать в качестве результата функции. Например, одной из распространенных ситуаций является возвращение из функции двух и более значений, в то время как функция может возвращать только одно значение. И кортежи представляют оптимальный способ для решения этой задачи:
var tuple = GetValues(); Console.WriteLine(tuple.Item1); // 1 Console.WriteLine(tuple.Item2); // 3 (int, int) GetValues() { var result = (1, 3); return result; }
Здесь определен метод GetValues()
, который возвращает кортеж. Кортеж определяется как набор значений, помещенных в круглые скобки.
И в данном случае мы возвращаем кортеж из двух элементов типа int, то есть два числа.
Другой пример:
var tuple = GetValuesData(new int[] { 1, 2, 3, 4, 5, 6, 7 }); Console.WriteLine(tuple.count); Console.WriteLine(tuple.sum); (int sum, int count) GetValuesData(int[] numbers) { var result = (sum: 0, count: numbers.Length); foreach(var n in numbers) { result.sum += n; } return result; }
И также кортеж может передаваться в качестве параметра в метод:
PrintPerson(("Tom", 37)); // Tom - 37 PrintPerson(("Bob", 41)); // Bob - 41 void PrintPerson((string name, int age) person) { Console.WriteLine($"{person.name} - {person.age}"); }
Здесь в метод PrintPerson передается кортеж из двух элементов, первый из которых предоставляет строку, а второй - значение типа int.