Codectionary / Developer documentation / C#

Tuples & Deconstruction

C# tuples let you group multiple values together without defining a dedicated class or struct, ideal for lightweight, temporary groupings like returning multiple values from a method. Modern C# (7+) supports named tuple elements for readability, and deconstruction syntax lets you unpack a tuple (or any type that supports it) into separate variables in one statement.

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
  1. Creating and accessing a tuple with named elements.
  2. 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.
  3. 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}");
  1. A very common use of tuples: avoiding an out parameter or a dedicated wrapper class.
  2. 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.
  3. 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}");
  1. Unpacking a tuple directly into separate named variables.
  2. 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.
  3. 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;
    }
}
  1. Any class or record can support deconstruction by defining a Deconstruct method (records get this automatically).
  2. 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.
  3. 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

Specifications & further reading