Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use C# tuple syntax to group a few related values when you need a lightweight, temporary result. Declare values in parentheses, give elements descriptive names for readable code, and access them by name or position. For longer-lived concepts or public API contracts, prefer a named record, class, or struct.

Declare a tuple and access its elements

A tuple type lists element types in parentheses; a tuple value lists corresponding values in the same order. Element names are optional, but they make code easier to read:

(double, int) unnamed = (4.5, 3);
Console.WriteLine(unnamed.Item1);

(double Sum, int Count) named = (4.5, 3);
Console.WriteLine($"Sum is {named.Sum} across {named.Count} elements.");

For an unnamed tuple, access elements with Item1, Item2, and so on. Named elements can be accessed by their declared names, such as Sum and Count. Names improve source-code clarity; they do not change the tuple’s positional behavior. See Microsoft’s C# value tuple reference.

Return multiple values from a method

A method can return a named tuple so callers receive several results without needing a separate type for a short-lived grouping:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
static (int Min, int Max) GetLimits(int[] values)
{
    return (values.Min(), values.Max());
}

var limits = GetLimits(new[] { 3, 8, 2 });
Console.WriteLine($"{limits.Min}..{limits.Max}");

The return type supplies the element names, and the returned values correspond to those elements by position. This example uses Min() and Max() from LINQ, so include using System.Linq; when implicit or global usings do not provide it. Microsoft’s tuples fundamentals guide covers tuple returns and use.

Deconstruct a tuple into variables

Deconstruction assigns tuple elements to separate variables in positional order. Use var to infer their types:

var (min, max) = GetLimits(new[] { 3, 8, 2 });
Console.WriteLine($"Minimum: {min}; maximum: {max}");

You can also deconstruct a tuple that already exists. Use _ as a discard for an element you do not need:

var pointAndLabel = (X: 2, Y: 5, Label: "sample");
var (x, _, _) = pointAndLabel;

Each position in the deconstruction corresponds to one tuple element. Discards let you ignore values without assigning them to named variables. See Microsoft’s tuples and deconstruction guidance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Assign and compare tuples by position

Tuple element names do not affect assignment or equality. What matters is the number of elements, their corresponding types, and—when comparing—the availability of equality operators for those element types:

(int A, int B) left = (1, 2);
(int X, int Y) right = left; // assignment follows positions
bool same = left == right;  // names do not affect equality

Tuple assignment requires the same number of elements and compatible corresponding element types. Equality compares values in order, and the tuples must have the same number of elements. The element expressions are evaluated before comparison; comparisons then stop at the first unequal pair. Microsoft’s C# value tuple reference documents these rules.

What C# tuple syntax represents

C# tuple syntax is implemented with the System.ValueTuple family of value types. These types expose mutable fields, including Item1 and Item2. This differs from the separate System.Tuple family, which consists of reference types with immutable properties. The syntax is a convenient way to use value tuples; it does not create a custom type with its own methods. The runtime types do provide .NET methods such as ToString() and GetHashCode().

.NET provides built-in value tuple structures for one through seven generic elements, plus an eight-or-more-element form that uses TRest. C# syntax can represent larger tuples, but a long list of positions is often harder to understand than a named type. A one-element tuple expression is not valid C# tuple syntax: tuples require at least two elements. See the value tuple reference and Microsoft’s CS8124 compiler diagnostic.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose a tuple or a named type

Tuples are most useful for grouping loosely related values that travel together briefly—for example, a method’s small multi-value result. Choose a named record, class, or struct when the grouping represents a durable concept, needs behavior or invariants, or is part of a public API abstraction.

Consideration Tuple is a good fit when… Prefer a named type when…
Lifespan The values are a temporary local or method result. The concept persists across the application or has a long-lived role.
Meaning The elements are loosely related and their names make the grouping clear. The values form a coherent concept that deserves its own name.
Behavior You need a simple data grouping. The type needs methods, invariants, or richer semantics.
API surface The convenience is internal or local. You are defining a stable public API contract.

Microsoft’s C# language reference puts the rule plainly: “Typically, use tuples to group loosely related data elements. In public APIs, consider defining a class or a structure type.” The C# tuple reference and tuples fundamentals guide also recommend considering records, classes, or structs for long-lived domain concepts or values with behavior.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.