How it works
A tuple groups a small set of related values without declaring a separate named type. Named tuple elements make a result easier to read at a call site, and deconstruction assigns the elements to local variables in one statement. This is useful for tightly related outputs such as a minimum and maximum, a quotient and remainder, or a total and item count.
Tuple element names improve source readability but do not create a new domain type. Two tuples with matching element types can be compatible even when their element names differ. When the result has important invariants, appears throughout an application, or needs behavior, a record or class may communicate the contract better than an expanding list of tuple positions.
Walk through the example. The Bounds function calculates the smallest and largest values from a known nonempty array and returns both under descriptive names. The first call accesses those names directly. The second deconstructs the same result into low and high, then prints the span. The original array is never modified by the calculation.
Watch the boundary. A tuple does not make its contents deeply immutable. If one element is a list, copying the tuple still shares that list. Also define what your function should do for an empty input; Min and Max cannot supply ordinary integer answers for an empty nonnullable sequence. Do not let a convenient return shape replace an input contract.
Practice independently. Write a function returning both the accepted count and rejected count from a collection of integer ages. Deconstruct the result and print a summary. Test no inputs, all valid inputs, all invalid inputs, and a mixture. Then decide whether a third or fourth result would still be clear as a tuple, or whether a named summary record would make future changes easier to understand.
A working example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
(int Minimum, int Maximum) Bounds(int[] values) => (values.Min(), values.Max());
int[] numbers = { 8, 2, 11, 5 };
var bounds = Bounds(numbers);
Console.WriteLine($"{bounds.Minimum}:{bounds.Maximum}");
var (low, high) = Bounds(numbers);
Console.WriteLine(high - low);
Expected output
2:11 9
Give tuple elements names, and specify the empty-input contract separately.