Read the syntax
A tuple groups several values without defining a custom class. Named elements improve readability, while unnamed elements remain available through Item1, Item2 and so on.
Deconstruction copies tuple elements into variables. A custom type can support the same syntax by defining a suitable Deconstruct method with out parameters.
Syntax
(type1 name1, type2 name2) tuple = (value1, value2);Examples
Basic Tuples
Creating and accessing a tuple with named elements.
(string Name, int Age) person = ("John", 21);
Console.WriteLine(person.Name); // John
Console.WriteLine(person.Age); // 21
// Without names, elements are accessed as Item1, Item2, etc.
var point = (3, 4);
Console.WriteLine(point.Item1); // 3- Creating and accessing a tuple with named elements.
- A tuple groups several values without defining a custom class. Named elements improve readability, while unnamed elements remain available through Item1, Item2 and so on.
- The named tuple prints John and 21 through Name and Age. The unnamed point exposes its first component as Item1, which prints 3.
Returning Multiple Values from a Method
A very common use of tuples: avoiding an out parameter or a dedicated wrapper class.
(int Min, int Max) GetMinMax(List<int> numbers)
{
return (numbers.Min(), numbers.Max());
}
var result = GetMinMax(new List<int> { 4, 1, 9, 2, 7 });
Console.WriteLine($"Min: {result.Min}, Max: {result.Max}");- A very common use of tuples: avoiding an out parameter or a dedicated wrapper class.
- A tuple groups several values without defining a custom class. Named elements improve readability, while unnamed elements remain available through Item1, Item2 and so on.
- GetMinMax calls Min and Max on the supplied list and returns both results as a tuple. The caller prints 1 and 9.
Deconstruction
Unpacking a tuple directly into separate named variables.
(int Min, int Max) GetMinMax(List<int> numbers) => (numbers.Min(), numbers.Max());
var (low, high) = GetMinMax(new List<int> { 4, 1, 9, 2, 7 });
Console.WriteLine($"Low: {low}, High: {high}");- Unpacking a tuple directly into separate named variables.
- A tuple groups several values without defining a custom class. Named elements improve readability, while unnamed elements remain available through Item1, Item2 and so on.
- The returned tuple is deconstructed directly into low and high. They hold 1 and 9, which the final interpolation prints.
Deconstructing Custom Types
Any class or record can support deconstruction by defining a Deconstruct method (records get this automatically).
Point p = new Point(3, 4);
var (x, y) = p; // uses the custom Deconstruct method
Console.WriteLine($"x={x}, y={y}");
public class Point
{
public int X, Y;
public Point(int x, int y) { X = x; Y = y; }
public void Deconstruct(out int x, out int y)
{
x = X;
y = Y;
}
}- Any class or record can support deconstruction by defining a Deconstruct method (records get this automatically).
- A tuple groups several values without defining a custom class. Named elements improve readability, while unnamed elements remain available through Item1, Item2 and so on.
- Point.Deconstruct assigns X and Y to its out parameters. The caller receives 3 and 4 in x and y and prints them.
Best practices
- Use named tuple elements ((string Name, int Age)) instead of the default Item1/Item2 for significantly better readability at call sites
- Use tuples for small, temporary, internal groupings - switch to a record or class once the data has real identity or is passed around extensively
- Use deconstruction (var (a, b) = tuple;) when you plan to use the individual values by name, rather than repeatedly writing result.Item1
- Add a Deconstruct method to your own classes when destructuring them into separate variables would be a common, natural usage pattern
Runtime & versions
.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
C# language reference