C# Fundamentals: From Your First Program to Async and JSON · C# Basics: Types, Collections, Classes and Pattern Matching

Control Flow, Methods and Tuples

Branch with if and switch expressions, loop with for, foreach and while, write methods with optional and named arguments, and return several values with tuples.

Create a free account to save this page, take notes and track your progress. Sign in

What you'll build

A grading helper: methods that classify scores with a switch expression, compute statistics and return several results as a tuple, with loops that process a list of students.

The idea

Branching: if/else, the ternary cond ? a : b, and switch. Prefer the switch expression, which returns a value and supports relational patterns (>= 90):

string grade = score switch { >= 90 => "A", >= 80 => "B", _ => "C" };

_ is the discard, matching anything else.

Loops: for (index), foreach (each item, the usual choice), while/do-while, with break and continue.

Methods:

  • Parameters can be optional (int decimals = 1) and passed by name (Round(x, decimals: 2)).
  • params takes any number of arguments: Sum(params int[] numbers).
  • Expression-bodied methods: static int Square(int n) => n * n;.
  • Local functions live inside another method.
  • Tuples return several values without defining a type: (double Min, double Max) Range(...). Deconstruct with var (min, max) = Range(...).

Methods in top-level programs are written as local functions, or in a class below the statements.

The code

Switch expressions, loops and tuple returns
var students = new Dictionary<string, int[]>
{
    ["Ada"] = [92, 88, 95],
    ["Grace"] = [78, 85, 80],
    ["Linus"] = [55, 62, 70],
};

foreach (var (name, scores) in students.OrderBy(s => s.Key))
{
    var (min, max, average) = Summarize(scores);
    Console.WriteLine($"{name,-6} min {min} max {max} avg {average:F1} grade {GradeFor(average)}");
}

// A while loop with break and continue
var numbers = new[] { 3, 8, 15, 4, 23, 42, 7 };
var index = 0;
var firstBig = -1;
while (index < numbers.Length)
{
    if (numbers[index] % 2 == 1) { index++; continue; }   // skip odd numbers
    if (numbers[index] > 30) { firstBig = numbers[index]; break; }
    index++;
}
Console.WriteLine($"first even number above 30: {firstBig}");

Console.WriteLine(Describe(5));
Console.WriteLine(Describe(5, unit: "km"));
Console.WriteLine(Join("-", "a", "b", "c"));

// A switch expression with relational patterns
static string GradeFor(double score) => score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    _ => "F",
};

// A tuple return, with named elements
static (int Min, int Max, double Average) Summarize(int[] scores) =>
    (scores.Min(), scores.Max(), scores.Average());

// Optional parameter with a default; callers can name arguments
static string Describe(int value, string unit = "m") => $"{value} {unit}";

// params accepts any number of arguments
static string Join(string separator, params string[] parts) => string.Join(separator, parts);

Output

Ada    min 88 max 95 avg 91.7 grade A
Grace  min 78 max 85 avg 81.0 grade B
Linus  min 55 max 70 avg 62.3 grade F
first even number above 30: 42
5 m
5 km
a-b-c

Run this on your computer — see “Get Started” for setup.

Common mistakes

  • Using switch statements with fall-through habits. C# requires break or return per case; switch expressions avoid the issue.
  • Modifying a collection while iterating it with foreach. It throws InvalidOperationException; collect changes first or iterate a copy.
  • Overusing optional parameters in public APIs. Defaults are baked into callers at compile time; overloads are safer for libraries.
  • Returning big tuples. Beyond three or so values, a record with named properties is clearer.
  • Off-by-one errors with for. Prefer foreach, or for (var i = 0; i < items.Length; i++) with < not <=.

Key points

  • Switch expressions return values and support relational and other patterns.
  • foreach is the default loop; break and continue control flow.
  • Methods support optional, named and params arguments, and expression bodies.
  • Tuples return several values and deconstruct with var (a, b) = ....

Further reading: C# fundamentals: Methods.

Practice questions

What is the advantage of a switch expression over a switch statement?

Answer

It is an expression that returns a value, is more compact, supports relational and type patterns, and the compiler warns when cases are not exhaustive, so you can't forget to handle one.

When is a tuple a poor choice for a return value?

Answer

When it has many elements or is used widely. A record with named properties documents the meaning, can be extended and is easier to use across a codebase than a long tuple.

Open in the app to mark lessons complete, take notes and track your progress.

Was this page helpful?