Tuples and deconstruction
Group a few values without writing a class, return several results from a method, and unpack them into variables.
out parameters are clumsy. A tuple groups a few values into one lightweight value.
(string, double) a = ("B1", 6.0); // unnamed: Item1, Item2(string Mark, double Length) b = ("B2", 4.5); // named elementsvar c = (Mark: "B3", Length: 7.2); // names in the literal Console.WriteLine(a.Item1);Console.WriteLine(b.Mark);Console.WriteLine(c); // nice ToString Output
B1 B2 (B3, 7.2)
Returning several values
static (double Min, double Max, double Avg) Stats(double[] v) => (v.Min(), v.Max(), v.Average()); var s = Stats(new[] { 12.5, 40, 22, 8.5 });Console.WriteLine($"min {s.Min}, max {s.Max}, avg {s.Avg}"); Output
min 8.5, max 40, avg 20.75
Deconstruction
var (min, max, avg) = Stats(new[] { 12.5, 40, 22, 8.5 }); // three new variablesvar (_, top, _) = Stats(new[] { 3.0, 9.0 }); // _ discardsConsole.WriteLine($"{min} {max} {avg} {top}"); // swap without a temporary variableint x = 1, y = 2;(x, y) = (y, x);Console.WriteLine($"{x} {y}"); // deconstruct in a foreach over a dictionaryvar weights = new Dictionary<string, double> { ["IPE200"] = 22.4, ["IPE300"] = 42.2 };foreach (var (profile, kg) in weights) Console.WriteLine($"{profile}: {kg}"); Output
8.5 40 20.75 9 2 1 IPE200: 22.4 IPE300: 42.2
Deconstructing your own types
public readonly struct Point3(double x, double y, double z){ public double X { get; } = x; public double Y { get; } = y; public double Z { get; } = z; public void Deconstruct(out double x, out double y, out double z) => (x, y, z) = (X, Y, Z);} var (px, py, _) = new Point3(1, 2, 3);Console.WriteLine($"{px}, {py}");// records get Deconstruct automatically from their positional parameters Output
1, 2
Tuples vs classes and records
| Use | When |
|---|---|
Practice
static (int Quotient, int Remainder) Divide(int a, int b) and use deconstruction to print 17 ÷ 5 as “3 remainder 2”. Then use it to convert 200 minutes into hours and minutes.
Show the solution
static (int Quotient, int Remainder) Divide(int a, int b) => (a / b, a % b); var (q, r) = Divide(17, 5);Console.WriteLine($"{q} remainder {r}"); var (hours, minutes) = Divide(200, 60);Console.WriteLine($"{hours} h {minutes} min"); Output
3 remainder 2 3 h 20 min
Remember
Tuples group a few values: (string Mark, double Length).Return tuples to give back several results without outor a new class.Deconstruct with var (a, b) = …; use_to discard.Prefer records/classes for data that matters beyond one method.