Chapter 11 Composition Using Tuples

2 min read
Rapid overview

Chapter 11 — Composition using tuples

Purpose of this chapter: become fluent with tuples as a lightweight composition tool, understand the difference between System.ValueTuple and System.Tuple, and know when not to use tuples (especially in public APIs).


11.1 Introduction to tuples

Tuples are “a bag of values” grouped together without defining a dedicated type.

Good for:

  • Temporary grouping inside a method.
  • Returning multiple values without out parameters.

Be cautious:

  • Overusing tuples can create unclear code (unnamed semantics).

11.2 Tuple literals and tuple types

11.2.1 Syntax

var point = (x: 10, y: 20);
// point.x == 10

11.2.2 Inferred element names (C# 7.1)

Element names can often be inferred from variables/properties, reducing repetition.

11.2.3 Tuples as bags of variables

Guideline:

  • Use meaningful element names when the tuple survives more than a few lines.

11.3 Tuple types and conversions

Tuples have types: (int x, int y) etc.

Key ideas:

  • Conversions exist between tuple literals and tuple types when shapes match.
  • Conversions between tuple types rely on element types and compatibility rules.

11.3.6 Equality and inequality (C# 7.3)

Tuples support value-like equality comparisons (element-wise) in many cases.


11.4 Tuples in the CLR (System.ValueTuple)

11.4.1 System.ValueTuple<...>

Modern C# tuples are backed by ValueTuple:

  • Struct-based (value type)
  • Field-like elements (typically Item1, Item2, plus compiler-provided names)

11.4.5 Regular vs structural equality/ordering

Know there are different equality semantics in .NET:

  • Some comparisons are “regular” and some use structural comparisons via interfaces (especially for nested tuples/collections).

11.4.7 Large tuples

Big tuples get awkward quickly. Guideline:

  • If you need many elements, you probably need a named type (record/class) instead.

11.5 Alternatives to tuples

  • System.Tuple<...>: older, reference type, different ergonomics/perf characteristics.
  • Anonymous types: great for local projections (especially with LINQ).
  • Named types (DTO/record): best for stable contracts and public APIs.

11.6 Uses and recommendations

11.6.1 Nonpublic APIs and easily changed code

Tuples are best when you can refactor freely (internal/private code).

11.6.2 Local variables

Great for short-lived composition (e.g., parsing + returning two values).

11.6.3 Fields

Be careful: storing tuples in fields can leak “unnamed semantics” into your design.

11.6.4 Tuples and dynamic

Tuples don’t combine nicely with dynamic (you lose compile-time shape checking and element naming clarity).