Skip to content

Commit 9a63f44

Browse files
committed
First pass edit on patterns
1 parent ed6824e commit 9a63f44

File tree

6 files changed

+144
-259
lines changed

6 files changed

+144
-259
lines changed

docs/csharp/tour-of-csharp/tutorials/pattern-matching.md

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,58 @@
11
---
22
title: Pattern matching
3-
description: In this tutorial about pattern matching, you use your browser to learn C# interactively. You're going to write C# code and see the results of compiling and running your code directly in the browser.
4-
ms.date: 05/02/2025
3+
description: In this tutorial about pattern matching, you learn C#. You're going to write C# code and see the results of compiling and running your code.
4+
ms.date: 12/04/2025
55
---
66
# Match data against patterns
77

8-
This tutorial teaches you how to use pattern matching to inspect data in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of types in C#. These lessons teach you the fundamentals of the C# language.
9-
10-
> [!TIP]
11-
> When a code snippet block includes the "Run" button, that button opens the interactive window, or replaces the existing code in the interactive window. When the snippet doesn't include a "Run" button, you can copy the code and add it to the current interactive window.
8+
This tutorial teaches you how to use pattern matching to inspect data in C#. You write small amounts of code, then you compile and run that code. The tutorial contains a series of lessons that explore different kinds of patterns supported by C#. These lessons teach you the fundamentals of the C# language.
129

1310
The preceding tutorials demonstrated built-in types and types you define as tuples or records. Instances of these types can be checked against a *pattern*. Whether an instance matches a pattern determines the actions your program takes. In the examples below, you'll notice `?` after type names. This symbol allows the value of this type to be null (for example, `bool?` can be `true`, `false` or `null`). For more information, see [Nullable value types](../../language-reference/builtin-types/nullable-value-types.md). Let's start to explore how you can use patterns.
1411

12+
<< TO DO: Make your app >>
13+
1514
## Match a value
1615

17-
All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, press the "Run" button:
16+
All the examples in this tutorial use text input that represents a series of bank transactions as comma separated values (CSV) input. In each of the samples you can match the record against a pattern using either an `is` or `switch` expression. This first example splits each line on the `,` character and then *matches* the first string field against the value "DEPOSIT" or "WITHDRAWAL" using an `is` expression. When it matches, the transaction amount is added or deducted from the current account balance. To see it work, add the following code to your source file. Then, type `dotnet run` in the console window.
1817

19-
:::code language="csharp" interactive="try-dotnet-method" source="./snippets/PatternMatching/Program.cs" id="FirstExample":::
18+
:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="FirstExample":::
2019

2120
Examine the output. You can see that each line is processed by comparing the value of the text in the first field. The preceding sample could be similarly constructed using the `==` operator to test that two `string` values are equal. Comparing a variable to a constant is a basic building block for pattern matching. Let's explore more of the building blocks that are part of pattern matching.
2221

2322
## Enum matches
2423

25-
Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. To see it work, press the "Run" button:
24+
Another common use for pattern matching is to match on the values of an `enum` type. This next sample processes the input records to create a *tuple* where the first value is an `enum` value that notes a deposit or a withdrawal. The second value is the value of the transaction. Add the following code to the end of your source file. It defines the `TransactionType` enumeration:
25+
26+
:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="TransactionTypeEnum":::
27+
28+
Next, add a function to parse a bank transaction into a tuple that holds the transaction type and the value of the transaction. Add the following code before your declaration of the `TransactionType` enum:
29+
30+
:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="ParseTransaction":::
2631

27-
> [!WARNING]
28-
> Don't copy and paste. The interactive window must be reset to run the following samples. If you make a mistake, the window hangs, and you need to refresh the page to continue.
32+
Next, add a new loop to process the transaction data using the `TransactionType` enumeration you declared:
2933

30-
:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FirstEnumExample.cs" id="IsEnumValue":::
34+
:::code language="csharp" source="./snippets/PatternMatching/Program.cs" id="EnumPatternMatch":::
3135

3236
The preceding example also uses an `if` statement to check the value of an `enum` expression. Another form of pattern matching uses a `switch` expression. Let's explore that syntax and how you can use it.
3337

3438
## Exhaustive matches with `switch`
3539

36-
A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in the interactive window with the `switch` expression you copied. After you've modified the code, press the "Run" button at the top of the interactive window to run the new sample.
40+
A series of `if` statements can test a series of conditions. But, the compiler can't tell if a series of `if` statements are *exhaustive* or if later `if` conditions are *subsumed* by earlier conditions. *Exhaustive* means that all possible inputs are handled by one of the `if` or `else` clauses in the series of tests. If a series of `if` statements are exhaustive, every possible input satisfies at least one `if` or `else` clause. *Subsumption* means that a later `if` or `else` clause can't be reached because earlier `if` or `else` clauses match all possible inputs. For example, in the following example code, one clause never matches:
41+
42+
```csharp
43+
int n = GetNumber();
44+
45+
if (n < 20)
46+
Console.WriteLine("n is less than 20");
47+
else if (n < 10)
48+
Console.WriteLine("n is less than 10"); // unreachable
49+
else
50+
Console.WriteLine("n is greater than 20");
51+
```
52+
53+
The `else if` clause never matches because every number less than 10 is also less than 20. The `switch` expression ensures both of those characteristics are met, which results in fewer bugs in your apps. Let's try it and experiment. Copy the following code. Replace the two `if` statements in your `foreach` loop with the `switch` expression you copied. After you've modified the code, type `dotnet run` to run the new sample.
3754

38-
:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/EnumSwitchExample.cs" id="SwitchEnumValue":::
55+
:::code language="csharp" source="./snippets/PatternMatching/EnumSwitchExample.cs" id="SwitchEnumValue":::
3956

4057
When you run the code, you see that it works the same. To demonstrate *subsumption*, reorder the switch arms as shown in the following snippet:
4158

@@ -48,25 +65,25 @@ currentBalance += transaction switch
4865
};
4966
```
5067

51-
After you reorder the switch arms, press the "Run" button. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code.
68+
After you reorder the switch arms, type `dotnet run`. The compiler issues an error because the arm with `_` matches every value. As a result, that final arm with `TransactionType.Withdrawal` never runs. The compiler tells you that something's wrong in your code.
5269

5370
The compiler issues a warning if the expression tested in a `switch` expression could contain values that don't match any switch arm. If some values could fail to match any condition, the `switch` expression isn't *exhaustive*. The compiler also issues a warning if some values of the input don't match any of the switch arms. For example, if you remove the line with `_ => 0.0,`, any invalid values don't match. At run time, that would fail. Once you install the .NET SDK and build programs in your environment, you can test this behavior. The online experience doesn't display warnings in the output window.
5471

5572
## Type patterns
5673

57-
To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations at the bottom of the interactive window:
74+
To finish this tutorial, let's explore one more building block to pattern matching: the *type pattern*. A *type pattern* tests an expression at run time to see if it's the specified type. You can use a type test with either an `is` expression or a `switch` expression. Let's modify the current sample in two ways. First, instead of a tuple, let's build `Deposit` and `Withdrawal` record types that represent the transactions. Add the following declarations just at the end of the your code file:
5875

59-
:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="RecordDeclarations":::
76+
:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="RecordDeclarations":::
6077

61-
Next, add this method after the `Main` method to parse the text and return a series of records:
78+
Next, add this method just before the declaration of the `TransactionType` enumeration. It parses the text and return a series of records:
6279

63-
:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord":::
80+
:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="ParseToRecord":::
6481

65-
Finally, replace the `foreach` loop in the `Main` method with the following code:
82+
Finally, add the following code after the last `foreach` loop:
6683

67-
:::code language="csharp" interactive="try-dotnet" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="TypePattern":::
84+
:::code language="csharp" source="./snippets/PatternMatching/FinalExampleProgram.cs" id="TypePattern":::
6885

69-
Then, press the "Run" button to see the results. This final version tests the input against a *type*.
86+
Then, type `dotnet run` to see the results. This final version tests the input against a *type*.
7087

7188
Pattern matching provides a vocabulary to compare an expression against characteristics. Patterns can include the expression's type, values of types, property values, and combinations of them. Comparing expressions against a pattern can be more clear than multiple `if` comparisons. You explored some of the patterns you can use to match expressions. There are many more ways to use pattern matching in your applications. First, visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET SDK, create a project on your machine, and keep coding. As you explore, you can learn more about pattern matching in C# in the following articles:
7289

docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/EnumSwitchExample.cs

Lines changed: 0 additions & 76 deletions
This file was deleted.

docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FinalExampleProgram.cs

Lines changed: 0 additions & 79 deletions
This file was deleted.

docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/FirstEnumExample.cs

Lines changed: 0 additions & 74 deletions
This file was deleted.

docs/csharp/tour-of-csharp/tutorials/snippets/PatternMatching/PatternMatching.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net9.0</TargetFramework>
5+
<TargetFramework>net10.0</TargetFramework>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
</PropertyGroup>

0 commit comments

Comments
 (0)