Skip to content

Commit bf617fc

Browse files
pkulikovgewarrenBillWagner
authored
Moved and revised the is operator article (#23884)
* Moved and revised the is operator article * Apply suggestions from code review Co-authored-by: Genevieve Warren <[email protected]> * Update docs/csharp/language-reference/operators/type-testing-and-cast.md Co-authored-by: Bill Wagner <[email protected]> Co-authored-by: Genevieve Warren <[email protected]> Co-authored-by: Bill Wagner <[email protected]>
1 parent 7e34dec commit bf617fc

File tree

20 files changed

+134
-418
lines changed

20 files changed

+134
-418
lines changed

.openpublishing.redirection.json

+4
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,10 @@
12821282
"source_path": "docs/csharp/language-reference/keywords/interpolated-strings.md",
12831283
"redirect_url": "/dotnet/csharp/language-reference/tokens/interpolated"
12841284
},
1285+
{
1286+
"source_path": "docs/csharp/language-reference/keywords/is.md",
1287+
"redirect_url": "/dotnet/csharp/language-reference/operators/is"
1288+
},
12851289
{
12861290
"source_path": "docs/csharp/language-reference/keywords/iteration-statements.md",
12871291
"redirect_url": "/dotnet/csharp/language-reference/keywords/statement-keywords"

docs/csharp/discards.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,5 @@ Without assigning the task to a discard, the following code generates a compiler
7979
## See also
8080

8181
- [Deconstructing tuples and other types](deconstruct.md)
82-
- [`is` keyword](language-reference/keywords/is.md)
82+
- [`is` operator](language-reference/operators/is.md)
8383
- [`switch` keyword](language-reference/keywords/switch.md)

docs/csharp/language-reference/keywords/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Keywords are predefined, reserved identifiers that have special meanings to the
2828
|[finally](try-finally.md)|[fixed](fixed-statement.md)|[float](../builtin-types/floating-point-numeric-types.md)|[for](for.md)|
2929
|[foreach](foreach-in.md)|[goto](goto.md)|[if](if-else.md)|[implicit](../operators/user-defined-conversion-operators.md)|
3030
|[in](in.md)|[int](../builtin-types/integral-numeric-types.md)|[interface](interface.md)|[internal](internal.md)|
31-
|[is](is.md)|[lock](lock-statement.md)|[long](../builtin-types/integral-numeric-types.md)|[namespace](namespace.md)|
31+
|[is](../operators/is.md)|[lock](lock-statement.md)|[long](../builtin-types/integral-numeric-types.md)|[namespace](namespace.md)|
3232
|[new](../operators/new-operator.md)|[null](null.md)|[object](../builtin-types/reference-types.md)|[operator](../operators/operator-overloading.md)|
3333
|[out](out.md)|[override](override.md)|[params](params.md)|[private](private.md)|
3434
|[protected](protected.md)|[public](public.md)|[readonly](readonly.md)|[ref](ref.md)|

docs/csharp/language-reference/keywords/is.md

-128
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
title: "is operator - C# reference"
3+
description: "Learn about the C# is operator that matches an expression against a pattern"
4+
ms.date: 04/23/2021
5+
f1_keywords:
6+
- "is_CSharpKeyword"
7+
- "is"
8+
helpviewer_keywords:
9+
- "is keyword [C#]"
10+
ms.assetid: bc62316a-d41f-4f90-8300-c6f4f0556e43
11+
---
12+
# is operator (C# reference)
13+
14+
In C# 6 and earlier, the `is` operator checks if the result of an expression is compatible with a given type. For information about the type-testing `is` operator, see the [is operator](type-testing-and-cast.md#is-operator) section of the [Type-testing and cast operators](type-testing-and-cast.md) article.
15+
16+
Beginning with C# 7.0, you can also use the `is` operator to match an expression against a pattern, as the following example shows:
17+
18+
:::code language="csharp" source="snippets/shared/IsOperator.cs" id="IntroExample":::
19+
20+
In the preceding example, the `is` operator matches an expression against a [property pattern](patterns.md#property-pattern) with nested [constant](patterns.md#constant-pattern) and [relational](patterns.md#relational-patterns) patterns.
21+
22+
The `is` operator can be useful in the following scenarios:
23+
24+
- To check the run-time type of an expression, as the following example shows:
25+
26+
:::code language="csharp" source="snippets/shared/IsOperator.cs" id="DeclarationPattern":::
27+
28+
The preceding example shows the use of a [declaration pattern](patterns.md#declaration-and-type-patterns).
29+
30+
- To check for `null`, as the following example shows:
31+
32+
:::code language="csharp" source="snippets/shared/IsOperator.cs" id="NullCheck":::
33+
34+
When you match an expression against `null`, the compiler guarantees that no user-overloaded `==` or `!=` operator is invoked.
35+
36+
- Beginning with C# 9.0, you can use a [negation pattern](patterns.md#logical-patterns) to do a non-null check, as the following example shows:
37+
38+
:::code language="csharp" source="snippets/shared/IsOperator.cs" id="NonNullCheck":::
39+
40+
For the complete list of patterns supported by the `is` operator, see [Patterns](patterns.md).
41+
42+
## C# language specification
43+
44+
For more information, see [The is operator](~/_csharplang/spec/expressions.md#the-is-operator) section of the [C# language specification](~/_csharplang/spec/introduction.md) and the following C# language proposals:
45+
46+
- [Pattern matching](~/_csharplang/proposals/csharp-7.0/pattern-matching.md)
47+
- [Pattern matching with generics](~/_csharplang/proposals/csharp-7.1/generics-pattern-match.md)
48+
49+
## See also
50+
51+
- [C# reference](../index.md)
52+
- [C# operators and expressions](index.md)
53+
- [Patterns](patterns.md)
54+
- [Tutorial: Use pattern matching to build type-driven and data-driven algorithms](../../tutorials/pattern-matching.md)
55+
- [Type-testing and cast operators](../operators/type-testing-and-cast.md)

docs/csharp/language-reference/operators/patterns.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ helpviewer_keywords:
1616

1717
C# introduced pattern matching in C# 7.0. Since then, each major C# version extends pattern matching capabilities. The following C# expressions and statements support pattern matching:
1818

19-
- [`is` expression](../keywords/is.md)
19+
- [`is` expression](is.md)
2020
- `switch` [statement](../keywords/switch.md)
2121
- `switch` [expression](switch-expression.md) (introduced in C# 8.0)
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
3+
namespace operators
4+
{
5+
public static class IsOperator
6+
{
7+
public static void Examples()
8+
{
9+
DeclarationPattern();
10+
}
11+
12+
// <IntroExample>
13+
static bool IsFirstSummerMonday(DateTime date) => date is { Month: 6, Day: <=7, DayOfWeek: DayOfWeek.Monday };
14+
// </IntroExample>
15+
16+
private static void DeclarationPattern()
17+
{
18+
// <DeclarationPattern>
19+
int i = 34;
20+
object iBoxed = i;
21+
int? jNullable = 42;
22+
if (iBoxed is int a && jNullable is int b)
23+
{
24+
Console.WriteLine(a + b); // output 76
25+
}
26+
// </DeclarationPattern>
27+
}
28+
29+
private static void NullCheck(object input)
30+
{
31+
// <NullCheck>
32+
if (input is null)
33+
{
34+
return;
35+
}
36+
// </NullCheck>
37+
}
38+
39+
private static void NonNullCheck(object result)
40+
{
41+
// <NonNullCheck>
42+
if (result is not null)
43+
{
44+
Console.WriteLine(result.ToString());
45+
}
46+
// </NonNullCheck>
47+
}
48+
}
49+
}

docs/csharp/language-reference/operators/snippets/shared/Program.cs

+3
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ static async Task Main(string[] args)
111111
SwitchExpressions.Examples();
112112
Console.WriteLine();
113113

114+
Console.WriteLine("============= is operator example ==============");
115+
IsOperator.Examples();
116+
Console.WriteLine();
114117
}
115118
}
116119
}

docs/csharp/language-reference/operators/type-testing-and-cast.md

+12-2
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,19 @@ E is T
4242

4343
where `E` is an expression that returns a value and `T` is the name of a type or a type parameter. `E` cannot be an anonymous method or a lambda expression.
4444

45-
The `E is T` expression returns `true` if the result of `E` is non-null and can be converted to type `T` by a reference conversion, a boxing conversion, or an unboxing conversion; otherwise, it returns `false`. The `is` operator doesn't consider user-defined conversions.
45+
The `is` operator returns `true` when an expression result is non-null and any of the following conditions are true:
4646

47-
The following example demonstrates that the `is` operator returns `true` if the runtime type of an expression result derives from a given type, that is, there exists a reference conversion between types:
47+
- The run-time type of an expression result is `T`.
48+
49+
- The run-time type of an expression result derives from type `T`, implements interface `T`, or another [implicit reference conversion](~/_csharplang/spec/conversions.md#implicit-reference-conversions) exists from it to `T`.
50+
51+
- The run-time type of an expression result is a [nullable value type](../builtin-types/nullable-value-types.md) with the underlying type `T` and the <xref:System.Nullable%601.HasValue?displayProperty=nameWithType> is `true`.
52+
53+
- A [boxing](../../programming-guide/types/boxing-and-unboxing.md#boxing) or [unboxing](../../programming-guide/types/boxing-and-unboxing.md#unboxing) conversion exists from the run-time type of an expression result to type `T`.
54+
55+
The `is` operator doesn't consider user-defined conversions.
56+
57+
The following example demonstrates that the `is` operator returns `true` if the run-time type of an expression result derives from a given type, that is, there exists a reference conversion between types:
4858

4959
[!code-csharp[is with reference conversion](snippets/shared/TypeTestingAndConversionOperators.cs#IsWithReferenceConversion)]
5060

docs/csharp/toc.yml

+4-5
Original file line numberDiff line numberDiff line change
@@ -1108,10 +1108,6 @@ items:
11081108
href: language-reference/keywords/using-statement.md
11091109
- name: extern alias
11101110
href: language-reference/keywords/extern-alias.md
1111-
- name: Type-testing Keywords
1112-
items:
1113-
- name: is
1114-
href: language-reference/keywords/is.md
11151111
- name: Generic Type Constraint Keywords
11161112
items:
11171113
- name: new constraint
@@ -1261,6 +1257,9 @@ items:
12611257
- name: delegate operator
12621258
href: language-reference/operators/delegate-operator.md
12631259
displayName: anonymous
1260+
- name: is operator
1261+
href: language-reference/operators/is.md
1262+
displayName: pattern matching
12641263
- name: nameof expression
12651264
href: language-reference/operators/nameof.md
12661265
displayName: nameof operator
@@ -1274,7 +1273,7 @@ items:
12741273
displayName: stack allocation, span, stackalloc operator
12751274
- name: switch expression
12761275
href: language-reference/operators/switch-expression.md
1277-
displayName: "switch, pattern matching, patterns"
1276+
displayName: pattern matching, patterns
12781277
- name: true and false operators
12791278
href: language-reference/operators/true-false-operators.md
12801279
- name: with expression

docs/csharp/whats-new/csharp-7.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Discards are supported in the following scenarios:
100100

101101
- When deconstructing tuples or user-defined types.
102102
- When calling methods with [out](../language-reference/keywords/out-parameter-modifier.md) parameters.
103-
- In a pattern matching operation with the [is](../language-reference/keywords/is.md) and [switch](../language-reference/keywords/switch.md) statements.
103+
- In a pattern matching operation with the [is](../language-reference/operators/is.md) and [switch](../language-reference/keywords/switch.md) statements.
104104
- As a standalone identifier when you want to explicitly identify the value of an assignment as a discard.
105105

106106
The following example defines a `QueryCityDataForYears` method that returns a 6-tuple that contains data for a city for two different years. The method call in the example is concerned only with the two population values returned by the method and so treats the remaining values in the tuple as discards when it deconstructs the tuple.
@@ -115,7 +115,7 @@ For more information, see [Discards](../discards.md).
115115

116116
Pattern matching supports `is` expressions and `switch` expressions. Each enables inspecting an object and its properties to determine if that object satisfies the sought pattern. You use the `when` keyword to specify additional rules to the pattern.
117117

118-
The `is` pattern expression extends the familiar [`is` operator](../language-reference/keywords/is.md#pattern-matching-with-is) to query an object about its type and assign the result in one instruction. The following code checks if a variable is an `int`, and if so, adds it to the current sum:
118+
The `is` pattern expression extends the familiar [`is` operator](../language-reference/operators/is.md) to query an object about its type and assign the result in one instruction. The following code checks if a variable is an `int`, and if so, adds it to the current sum:
119119

120120
```csharp
121121
if (input is int count)

0 commit comments

Comments
 (0)