-
Notifications
You must be signed in to change notification settings - Fork 6k
C# patterns reference: declaration and type patterns #22844
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
BillWagner
merged 7 commits into
dotnet:csharp-patterns-reference
from
pkulikov:csharp-patterns-reference-type-pattern
Feb 20, 2021
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
a0d1095
C# patterns reference: declaration and type patterns
pkulikov 44625b3
Added trailing new line
pkulikov f6f2591
Addressed feedback in code
pkulikov 131de2e
Apply suggestions from code review
pkulikov b90ef31
Addressed feedback about scope
pkulikov e6bb7c8
Restructure
pkulikov 00caff4
Apply suggestions from code review
pkulikov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
title: "Patterns - C# reference" | ||
description: "Learn about the patterns supported by C# switch and is expressions and C# switch statement - C# reference" | ||
ms.date: 02/18/2021 | ||
helpviewer_keywords: | ||
- "pattern matching [C#]" | ||
--- | ||
# Patterns (C# reference) | ||
|
||
Intro. | ||
|
||
## Declaration and type patterns | ||
|
||
You use the declaration and type patterns to check if the runtime type of an expression is compatible with the given type. With the declaration pattern, you can also declare a new local variable. That variable is assigned a converted expression result when a pattern matches an expression. | ||
|
||
Beginning with C# 7.0, *declaration pattern* `T v` matches expression `E` when the result of `E` is non-null and any of the following conditions are true: | ||
|
||
- The runtime type of `E` is `T`. | ||
|
||
- The runtime type of `E` derives from type `T` or implements interface `T` or there exists another [implicit reference conversion](~/_csharplang/spec/conversions.md#implicit-reference-conversions) from it to type `T`. The following example demonstrates two cases when this condition is true: | ||
|
||
:::code language="csharp" source="snippets/patterns/DeclarationAndTypePattern.cs" id="ReferenceConversion"::: | ||
|
||
In the preceding example, at the first call to the `GetSourceLabel` method, an argument value is matched by the first pattern because its runtime type `int[]` derives from the <xref:System.Array> type. At the second call to the `GetSourceLabel` method, the runtime type of an argument is <xref:System.Collections.Generic.List%601> that doesn't derive from the <xref:System.Array> type but implements the <xref:System.Collections.Generic.ICollection%601> interface. | ||
|
||
- The runtime type of `E` is a [nullable value type](../builtin-types/nullable-value-types.md) with the underlying type `T`. | ||
|
||
- A [boxing](../../programming-guide/types/boxing-and-unboxing.md#boxing) or [unboxing](../../programming-guide/types/boxing-and-unboxing.md#unboxing) conversion exists from the runtime type of `E` to type `T`. | ||
|
||
The following example demonstrates the last two of the preceding conditions: | ||
|
||
:::code language="csharp" source="snippets/patterns/DeclarationAndTypePattern.cs" id="NullableAndUnboxing"::: | ||
|
||
If you want to check only the type of an expression, you can use a discard `_` in place of a variable name as the following example shows: | ||
|
||
:::code language="csharp" source="snippets/patterns/DeclarationAndTypePattern.cs" id="DiscardVariable"::: | ||
|
||
Beginning with C# 9.0, for that purpose you can use the *type pattern* as the following example shows: | ||
|
||
:::code language="csharp" source="snippets/patterns/DeclarationAndTypePattern.cs" id="TypePattern"::: | ||
|
||
Like a declaration pattern, a type pattern matches an expression when an expression result is non-null and its runtime type satisfies any of the conditions listed above. | ||
|
||
## C# language specification | ||
|
||
For more information, see the following feature proposal notes: | ||
|
||
- [Pattern matching for C# 7.0](~/_csharplang/proposals/csharp-7.0/pattern-matching.md) | ||
- [Recursive pattern matching (introduced in C# 8.0)](~/_csharplang/proposals/csharp-8.0/patterns.md) | ||
- [Pattern-matching changes for C# 9.0](~/_csharplang/proposals/csharp-9.0/patterns3.md) | ||
|
||
## See also | ||
|
||
- [C# reference](../index.md) | ||
- [C# operators and expressions](index.md) | ||
- [Tutorial: Use pattern matching to build type-driven and data-driven algorithms](../../tutorials/pattern-matching.md) |
79 changes: 79 additions & 0 deletions
79
docs/csharp/language-reference/operators/snippets/patterns/DeclarationAndTypePattern.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Patterns | ||
{ | ||
public static class DeclarationAndTypePattern | ||
{ | ||
public static void Examples() | ||
{ | ||
ReferenceConversion(); | ||
NullableAndUnboxing(); | ||
} | ||
|
||
private static void ReferenceConversion() | ||
{ | ||
// <ReferenceConversion> | ||
var numbers = new int[] { 10, 20, 30 }; | ||
Console.WriteLine(GetSourceLabel(numbers)); // output: 1 | ||
|
||
var letters = new List<char> { 'a', 'b', 'c', 'd' }; | ||
Console.WriteLine(GetSourceLabel(letters)); // output: 2 | ||
|
||
static int GetSourceLabel<T>(IEnumerable<T> source) => source switch | ||
{ | ||
Array array => 1, | ||
ICollection<T> collection => 2, | ||
_ => 3, | ||
}; | ||
// </ReferenceConversion> | ||
} | ||
|
||
private static void NullableAndUnboxing() | ||
{ | ||
// <NullableAndUnboxing> | ||
int? xNullable = 7; | ||
int y = 23; | ||
object yBoxed = y; | ||
if (xNullable is int a && yBoxed is int b) | ||
{ | ||
Console.WriteLine(a + b); // output: 30 | ||
} | ||
// </NullableAndUnboxing> | ||
} | ||
} | ||
|
||
namespace Vehicles | ||
{ | ||
// <DiscardVariable> | ||
public abstract class Vehicle {} | ||
public class Car : Vehicle {} | ||
public class Truck : Vehicle {} | ||
|
||
public static class TollCalculator | ||
pkulikov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch | ||
{ | ||
Car _ => 2.00m, | ||
Truck _ => 7.50m, | ||
null => throw new ArgumentNullException(nameof(vehicle)), | ||
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)), | ||
}; | ||
} | ||
// </DiscardVariable> | ||
|
||
public static class TollCalculatorWithTypePattern | ||
{ | ||
// <TypePattern> | ||
public static decimal CalculateToll(this Vehicle vehicle) => vehicle switch | ||
{ | ||
Car => 2.00m, | ||
Truck => 7.50m, | ||
null => throw new ArgumentNullException(nameof(vehicle)), | ||
_ => throw new ArgumentException("Unknown type of a vehicle", nameof(vehicle)), | ||
}; | ||
// </TypePattern> | ||
} | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
docs/csharp/language-reference/operators/snippets/patterns/Program.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
|
||
namespace Patterns | ||
{ | ||
class Program | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
Console.WriteLine("--- Declaration and type pattern examples ---"); | ||
DeclarationAndTypePattern.Examples(); | ||
Console.WriteLine(); | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
docs/csharp/language-reference/operators/snippets/patterns/patterns.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net5.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<RootNamespace>Patterns</RootNamespace> | ||
<StartupObject>Patterns.Program</StartupObject> | ||
</PropertyGroup> | ||
|
||
</Project> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.