Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions docs/csharp/fundamentals/statements/iteration-statements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: "Iteration statements in C#"
description: Use foreach, while, do-while, and for to repeat a block of code, and use break and continue to control the flow of a loop.
ms.date: 07/09/2026
ms.topic: concept-article
ai-usage: ai-assisted
---

# Iteration statements

> [!TIP]
> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../tour-of-csharp/tutorials/index.md) tutorials first. For the complete syntax, see [iteration statements](../../language-reference/statements/iteration-statements.md) in the language reference.
>
> **Coming from another language?** All four C# loops (`foreach`, `while`, `do`-`while`, and `for`) have direct equivalents in Java, C++, and JavaScript. The one to reach for most is `foreach`, which iterates a collection without an index, like Java's enhanced `for` or JavaScript's `for...of`.

Iteration statements run a block of code repeatedly. Each pass through the block is an *iteration*, and a repeating block is a *loop*. C# provides four loops. Start with `foreach` for collections, use `while` and `do`-`while` when a condition controls the repetition, and use `for` when you need an explicit index.

## Iterate a collection with `foreach`

The `foreach` statement runs its body once for each element in a collection, in order. It's the default choice for reading a collection because you don't manage an index or a bounds check, which removes a whole class of off-by-one errors:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="Foreach":::

`foreach` works with any type that C# recognizes as a sequence, including arrays, <xref:System.Collections.Generic.List`1>, and <xref:System.Collections.Generic.Dictionary`2>. The iteration variable (`name` in the previous example) is read-only, so you can't reassign it inside the loop.

## Repeat while a condition holds with `while`

A `while` loop checks its Boolean condition *before* each iteration. If the condition is `false` at the start, the body never runs, so a `while` loop runs zero or more times:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="While":::

Make sure something inside the loop changes the condition. In the previous example, `countdown--` eventually makes the condition `false`. A loop whose condition never becomes `false` runs forever.

## Run the body at least once with `do`-`while`

A `do`-`while` loop checks its condition *after* each iteration, so the body always runs at least once. Use it when the first pass must happen before you can evaluate the condition, such as prompting for input and then validating it:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="DoWhile":::

## Count with `for`

A `for` loop packs three parts into its header: an *initializer* that runs once before the loop, a *condition* that's checked before each iteration, and an *iterator* that runs after each iteration. Reach for `for` when you need the index itself, not just the elements:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="For":::

When you only need the elements and not their positions, prefer `foreach`. It states the intent more clearly and avoids index arithmetic.

## Exit or skip with `break` and `continue`

Two jump statements give you finer control inside any loop. The `break` statement exits the loop immediately, skipping any remaining iterations:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="Break":::

The `continue` statement skips the rest of the current iteration and moves on to the next one:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="Continue":::

## Iterate an asynchronous stream with `await foreach`

When elements arrive over time, such as pages from a web API or rows from a database, a collection can produce them asynchronously as an <xref:System.Collections.Generic.IAsyncEnumerable`1>. Use `await foreach` to consume such a stream: each iteration can suspend while the next element is produced, without blocking the thread:

:::code language="csharp" source="./snippets/iteration-statements/Program.cs" id="AwaitForeach":::

Asynchronous streams build on `async` and `await`. For a full walkthrough, see [Generate and consume asynchronous streams](../../asynchronous-programming/generate-consume-asynchronous-stream.md).

## See also

- [Selection statements](selection-statements.md)
- [Iteration statements (language reference)](../../language-reference/statements/iteration-statements.md)
- [Generate and consume asynchronous streams](../../asynchronous-programming/generate-consume-asynchronous-stream.md)
67 changes: 67 additions & 0 deletions docs/csharp/fundamentals/statements/selection-statements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
---
title: "Selection statements in C#"
description: Use if, else, and switch statements to choose which code runs based on a condition, including pattern-based case labels and when clauses.
ms.date: 07/09/2026
ms.topic: concept-article
ai-usage: ai-assisted
---

# Selection statements

> [!TIP]
> This article is part of the **Fundamentals** section for developers who already know at least one programming language and are learning C#. If you're new to programming, start with the [Get started](../../tour-of-csharp/tutorials/index.md) tutorials first. For the complete syntax, see [selection statements](../../language-reference/statements/selection-statements.md) in the language reference.
>
> **Coming from another language?** C#'s `if` and `else` work as they do in Java, C++, and JavaScript. The `switch` statement looks familiar too, but C# forbids fall-through between cases, and each `case` label can test a *pattern* rather than only a constant.

Selection statements choose which block of code runs based on a condition. C# provides two: `if` (with an optional `else`) for branching on a Boolean value, and `switch` for comparing one value against several cases. A *Boolean expression* is any expression that evaluates to `true` or `false`, such as the comparison `temperature >= 25`.

## Branch with `if` and `else`

An `if` statement runs its block only when its Boolean expression is `true`. Add an `else` block to supply the code that runs when the condition is `false`:

:::code language="csharp" source="./snippets/selection-statements/Program.cs" id="IfElse":::

Always enclose the branch bodies in braces (`{ }`), even for a single statement. Braces make the scope explicit and prevent a common mistake: adding a second line later that you expect to run conditionally, but that runs unconditionally instead.

## Test several conditions with `else if`

To choose among more than two paths, chain conditions with `else if`. C# evaluates each condition in order and runs the first block whose condition is `true`, then skips the rest. A final `else` handles every remaining case:

:::code language="csharp" source="./snippets/selection-statements/Program.cs" id="ElseIf":::

Order matters in a chain. Because the first matching condition wins, put the most specific conditions first. In the previous example, testing `score >= 80` before `score >= 70` ensures a score of 82 maps to `"B"` rather than `"C"`.

## Match a value with `switch`

When you compare a single value against many discrete cases, a `switch` statement reads more clearly than a long `else if` chain. Each `case` label lists a value to match, and its section ends with a `break` statement. Stack labels to share one body, and use the `default` section for values that no case matches:

:::code language="csharp" source="./snippets/selection-statements/Program.cs" id="SwitchStatement":::

Unlike C and Java, C# doesn't allow execution to fall through from one nonempty `case` section into the next. Every section that contains code must end with a `break` (or another jump statement, such as `return`). This rule prevents the accidental fall-through bugs common in those languages.

### Test patterns with `case` and `when`

A `case` label isn't limited to constant values. It can test a *pattern*, which is a rule that describes the shape or value of data. A relational pattern such as `< 0` matches any value less than zero. Add a `when` clause to attach an extra condition that must also be `true` for the case to match:

:::code language="csharp" source="./snippets/selection-statements/Program.cs" id="SwitchWhen":::

Pattern-based cases are evaluated top to bottom, so more specific patterns belong before more general ones. For the full catalog of patterns, see [pattern matching](../functional/pattern-matching.md).

## Choose a value with the conditional operator

When both branches produce a *value* rather than run different statements, the conditional operator `?:` expresses the choice in a single expression. It takes the form `condition ? valueIfTrue : valueIfFalse`:

:::code language="csharp" source="./snippets/selection-statements/Program.cs" id="Ternary":::

Reach for `?:` when you assign one of two values, because it keeps the assignment in one place and makes the variable easy to mark `readonly` or `const`. Prefer an `if` statement when the branches do more than produce a value. For the operator's precedence and associativity rules, see the [conditional operator](../../language-reference/operators/conditional-operator.md) in the language reference.

## From `switch` statements to `switch` expressions

A `switch` *statement* runs code. When every case instead produces a value, a `switch` *expression* is more concise: it returns a value directly, and the compiler warns you if the cases don't cover every possible input. The `switch` expression is a core part of pattern matching. To learn when and how to use it, see [pattern matching](../functional/pattern-matching.md) and the [`switch` expression](../../language-reference/operators/switch-expression.md) reference.

## See also

- [Iteration statements](iteration-statements.md)
- [Pattern matching](../functional/pattern-matching.md)
- [Selection statements (language reference)](../../language-reference/statements/selection-statements.md)
- [Conditional operator (language reference)](../../language-reference/operators/conditional-operator.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
namespace IterationStatements;

public static class Program
{
public static async Task Main()
{
ForeachExample();
WhileExample();
DoWhileExample();
ForExample();
BreakExample();
ContinueExample();
await AwaitForeachExample();
}

private static void ForeachExample()
{
// <Foreach>
string[] names = ["Ana", "Ben", "Cleo"];

// foreach reads each element in order. It's the default loop for
// collections: no index to manage and no off-by-one mistakes.
foreach (string name in names)
{
Console.WriteLine(name); // => Ana, then Ben, then Cleo
}
// </Foreach>
}

private static void WhileExample()
{
// <While>
int countdown = 3;

// A while loop checks its condition before each iteration, so the body
// runs zero or more times.
while (countdown > 0)
{
Console.WriteLine(countdown); // => 3, then 2, then 1
countdown--;
}
// </While>
}

private static void DoWhileExample()
{
// <DoWhile>
int attempts = 0;

// A do-while loop runs its body once, then checks the condition. Use it
// when the body must run at least one time.
do
{
attempts++;
Console.WriteLine($"Attempt {attempts}"); // => Attempt 1
}
while (attempts < 1);
// </DoWhile>
}

private static void ForExample()
{
// <For>
// A for loop fits when you need an explicit index. The three parts are
// the initializer, the condition, and the iterator.
for (int i = 0; i < 3; i++)
{
Console.WriteLine(i); // => 0, then 1, then 2
}
// </For>
}

private static void BreakExample()
{
// <Break>
int[] numbers = [2, 4, 7, 8];

// break stops the loop immediately, skipping any remaining elements.
foreach (int number in numbers)
{
if (number % 2 != 0)
{
Console.WriteLine($"First odd number: {number}"); // => First odd number: 7
break;
}
}
// </Break>
}

private static void ContinueExample()
{
// <Continue>
int[] values = [1, 2, 3, 4, 5];

// continue skips the rest of the current iteration and moves to the next.
foreach (int value in values)
{
if (value % 2 == 0)
{
continue; // skip even numbers
}

Console.WriteLine(value); // => 1, then 3, then 5
}
// </Continue>
}

// <AwaitForeach>
private static async Task AwaitForeachExample()
{
// await foreach consumes an asynchronous stream. Each iteration can
// suspend while the next element is produced.
await foreach (int value in GenerateAsync())
{
Console.WriteLine(value); // => 0, then 1, then 2
}
}

private static async IAsyncEnumerable<int> GenerateAsync()
{
for (int i = 0; i < 3; i++)
{
await Task.Delay(1); // stand-in for real asynchronous work
yield return i;
}
}
// </AwaitForeach>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
namespace SelectionStatements;

public static class Program
{
public static void Main()
{
IfElseExample();
ElseIfExample();
SwitchStatementExample();
SwitchWhenExample();
TernaryExample();
}

private static void IfElseExample()
{
// <IfElse>
int temperature = 28;

// An if statement runs its block only when the condition is true.
// The else block runs when the condition is false.
if (temperature >= 25)
{
Console.WriteLine("Warm"); // => Warm
}
else
{
Console.WriteLine("Cool");
}
// </IfElse>
}

private static void ElseIfExample()
{
// <ElseIf>
int score = 82;

// Chain conditions with else if. The first branch whose condition is
// true runs; the compiler skips the rest.
string grade;
if (score >= 90)
{
grade = "A";
}
else if (score >= 80)
{
grade = "B";
}
else if (score >= 70)
{
grade = "C";
}
else
{
grade = "F";
}

Console.WriteLine(grade); // => B
// </ElseIf>
}

private static void SwitchStatementExample()
{
// <SwitchStatement>
DayOfWeek day = DayOfWeek.Saturday;

// A switch statement compares one value against several case labels.
// Stacked labels share a body. Each section ends with break, and the
// default section runs when no case matches.
switch (day)
{
case DayOfWeek.Saturday:
case DayOfWeek.Sunday:
Console.WriteLine("Weekend"); // => Weekend
break;
default:
Console.WriteLine("Weekday");
break;
}
// </SwitchStatement>
}

private static void SwitchWhenExample()
{
// <SwitchWhen>
int measurement = 42;

// A case label can test a pattern instead of a constant. A when clause
// adds a condition that must also be true for the case to match.
switch (measurement)
{
case < 0:
Console.WriteLine("Negative");
break;
case 0:
Console.WriteLine("Zero");
break;
case > 0 when measurement % 2 == 0:
Console.WriteLine("Positive and even"); // => Positive and even
break;
default:
Console.WriteLine("Positive and odd");
break;
}
// </SwitchWhen>
}

private static void TernaryExample()
{
// <Ternary>
int hour = 9;

// The conditional operator ?: chooses between two values in a single
// expression: condition ? valueIfTrue : valueIfFalse.
string greeting = hour < 12 ? "Good morning" : "Good afternoon";

Console.WriteLine(greeting); // => Good morning
// </Ternary>
}
}
Loading
Loading