Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Подсказка
Вы новичок в разработке программного обеспечения? Начните с руководств Начало работы. При необходимости возвращать несколько значений из метода или группировать значения без определения именованного типа, вы столкнетесь с кортежами.
Есть опыт на другом языке? В языке C# кортежи представляют собой типы значений, аналогичные кортежам в Python и Swift, с возможностью использования необязательных именованных элементов и полной поддержкой деконструкции. Просмотрите разделы деконструкции и равенства, чтобы выявить шаблоны, специфичные для C#.
Кортеж группует несколько значений в одну упрощенную структуру, не требуя определения именованного типа. Кортежи — это типы значений, которые можно объявлять встроенными, возвращать из методов и деконструировать в отдельные переменные. Используйте кортежи, если требуется быстрая группирование связанных значений. Например, при возврате нескольких результатов из метода или хранения пары координат.
В следующем примере создается кортеж с именованными элементами, к которым можно обращаться по их именам.
var location = (Latitude: 47.6062, Longitude: -122.3321);
Console.WriteLine($"Location: {location.Latitude}, {location.Longitude}");
// Output: Location: 47.6062, -122.3321
Кортежи хорошо подходят для кратковременных объединений, в ситуации, когда определение класса, структуры или записи вносило бы необоснованное усложнение. Для долгосрочных концепций предметной области или типов с поведением, предпочитайте записи, классы или структуры. Сравнение того, когда следует использовать каждый из них, см. в разделе "Выбор типа".
Объявление и инициализация кортежей
Объявите кортеж, перечислив типы элементов в скобках. При необходимости можно присвоить имя каждому элементу, чтобы код читался легче.
// Tuple with named elements
(string Name, int Age) person = ("Alice", 30);
Console.WriteLine($"{person.Name} is {person.Age} years old");
// Tuple with default element names (Item1, Item2)
(string, int) unnamed = ("Bob", 25);
Console.WriteLine($"{unnamed.Item1} is {unnamed.Item2} years old");
// Tuple declared with var and inline names
var city = (Name: "Seattle", Population: 749_256);
Console.WriteLine($"{city.Name}: population {city.Population}");
Если имена не указаны, элементы используют имена Item1Item2по умолчанию и т. д. Именованные элементы делают ваш код самодокументируемым, что устраняет необходимость в определении отдельного типа.
Выводимые имена элементов
Компилятор выводит имена элементов из имен переменных или имен свойств, используемых для инициализации кортежа. Эта функция позволяет избежать избыточности при совпадении имен:
var name = "Carol";
var age = 28;
// The compiler infers element names from the variable names
var person = (name, age);
Console.WriteLine($"{person.name} is {person.age}");
// Output: Carol is 28
Выводимые имена сохраняют краткий код. Если требуется другое имя элемента, укажите его явным образом.
Возврат нескольких значений из метода
Одним из наиболее распространенных способов использования кортежей является возврат нескольких значений из метода. Вместо определения класса или использования out параметров возвращает кортеж с именованными элементами:
static (double Minimum, double Maximum, double Average) ComputeStats(List<double> values)
{
var min = values.Min();
var max = values.Max();
var avg = values.Average();
return (min, max, avg);
}
Именованные элементы кортежа делают возвращаемые значения читаемыми как на месте вызова, так и в описании метода. Вызывающий может получить доступ к каждому значению по имени без необходимости запоминать позиционный порядок.
Деконструкция кортежей
Деконструкция распаковывает элементы кортежа в отдельные переменные в одном операторе. Кортежи можно деконструировать несколькими способами:
var point = (X: 3, Y: 7);
// Deconstruct with var (infer all types)
var (x, y) = point;
Console.WriteLine($"x={x}, y={y}");
// Deconstruct with explicit types
(int px, int py) = point;
Console.WriteLine($"px={px}, py={py}");
// Deconstruct into existing variables
int a, b;
(a, b) = point;
Console.WriteLine($"a={a}, b={b}");
// Deconstruct a method return value directly
List<double> data = [10.0, 20.0, 30.0];
var (min, max, avg) = ComputeStats(data);
Console.WriteLine($"Min: {min}, Max: {max}, Avg: {avg}");
Деконструкция особенно полезна при получении кортежа из вызова метода и когда нужно сразу работать с его отдельными значениями.
Кортежи можно деконструировать непосредственно в foreach циклах, что делает итерацию по коллекциям сгруппированных значений кратким:
List<(string Name, int Score)> results =
[
("Alice", 92),
("Bob", 87),
("Carol", 95)
];
foreach (var (name, score) in results)
{
Console.WriteLine($"{name}: {score}");
}
Если вам не нужен каждый элемент, используйте отмену (_) вместо каждого значения, которое вы хотите игнорировать. Используйте отдельную _ позицию для каждой отклоненной позиции:
List<double> values = [5.0, 10.0, 15.0];
var (_, max, _) = ComputeStats(values);
Console.WriteLine($"Only need the max: {max}");
// Output: Only need the max: 15
Дополнительные сведения об использовании отбраковки в разных контекстах см. в разделе "Отбраковки".
Равенство кортежей
Вы можете сравнить кортежи с помощью == и !=. Эти операторы последовательно сравнивают каждый элемент, поэтому два кортежа равны, когда все их соответствующие элементы равны.
var order1 = (Product: "Widget", Quantity: 5);
var order2 = (Product: "Widget", Quantity: 5);
var order3 = (Product: "Gadget", Quantity: 3);
Console.WriteLine(order1 == order2); // True
Console.WriteLine(order1 == order3); // False
// Element names don't affect equality—only values matter
var named = (X: 1, Y: 2);
var different = (A: 1, B: 2);
Console.WriteLine(named == different); // True
Определенное оператором == равенство кортежей используется для каждого типа элемента, что означает, что сравнение корректно работает для строк, чисел и других типов, которые определяют ==. Имена элементов не влияют на сравнение — важны только значения и позиции.
Недеструктивная мутация с with
Выражение with создает копию кортежа с измененными одним или несколькими элементами, при этом оригинал остается без изменений.
var original = (Name: "Widget", Price: 19.99m, InStock: true);
var discounted = original with { Price = 14.99m };
Console.WriteLine($"Original: {original.Name} at {original.Price:C}");
Console.WriteLine($"Discounted: {discounted.Name} at {discounted.Price:C}");
// Output:
// Original: Widget at $19.99
// Discounted: Widget at $14.99
Этот шаблон полезен, если требуется вариант существующего кортежа без изменения исходного. Выражение with работает с кортежами так же, как и с записями.
Кортежи в словарях и поисках
Кортежи делают значения словаря удобными, когда необходимо связать ключ с несколькими элементами данных.
var sizeChart = new Dictionary<string, (int Min, int Max)>
{
["Small"] = (0, 50),
["Medium"] = (51, 100),
["Large"] = (101, 200)
};
if (sizeChart.TryGetValue("Medium", out var range))
{
Console.WriteLine($"Medium: {range.Min}–{range.Max}");
}
// Output: Medium: 51–100
Кортежи могут использоваться в качестве ключей в словаре, предоставляя возможность создания составного ключа без необходимости определения пользовательского типа. Поскольку кортежи реализуют структурное равенство, поиск осуществляется по комбинированным значениям всех элементов.
var grid = new Dictionary<(int Row, int Column), string>
{
[(0, 0)] = "Origin",
[(1, 3)] = "Sensor A",
[(2, 5)] = "Sensor B"
};
var target = (Row: 1, Column: 3);
if (grid.TryGetValue(target, out var label))
{
Console.WriteLine($"({target.Row}, {target.Column}): {label}");
}
// Output: (1, 3): Sensor A
Этот шаблон позволяет избежать необходимости в отдельном классе для простых поисков с несколькими ключами или сопоставлениями значений с несколькими ключами.
Кортежи и анонимные типы
Кортежи — это предпочтительный выбор, если вам нужна упрощенная структура данных без именованных данных. Анонимные типы по-прежнему применяются в сценариях дерева выражений и в коде, который требует ссылочных типов, но кортежи обеспечивают более высокую производительность, поддержку декомпозиции и более гибкий синтаксис. Дополнительные сведения об анонимных типах см. в разделе "Выбор между анонимными типами и типами кортежей".
См. также
- Типы кортежей (справочник по C#) для полных сведений о синтаксисе
-
Деконструкция кортежей и других типов для определяемых
Deconstructпользователем методов - Отбрасывания
- Записи