Skip to main content
A type pattern in C# is a pattern matching construct used to evaluate whether an expression’s runtime type is compatible with a specified target type. If the type check succeeds, the pattern evaluates to true. When combined with a variable designation, it forms a declaration pattern that binds the matched value to a newly declared local variable of the target type in a single, atomic operation.

Syntax

A true type pattern (introduced in C# 9.0) consists solely of the type name and is used within pattern contexts such as switch cases or logical patterns. When a variable name is appended, it becomes a declaration pattern.
Note: An expression of the exact form expression is Type (without a variable or logical combinator) is parsed by the compiler as a legacy C# 1.0 is-type expression for backward compatibility, rather than a C# 9.0 type pattern.

Mechanics and Evaluation Rules

  • Type Compatibility: The pattern evaluates to true if the runtime type of the expression is exactly the target type, derives from the target type, or implements the target interface. Unlike the as operator, which only works with reference types and nullable value types, type patterns natively handle unboxing conversions for non-nullable value types.
  • Null Safety: An expression that evaluates to null will strictly evaluate to false against any type pattern. Type patterns inherently guarantee that the matched expression is not null.
  • Nullable Value Types: Nullable value types (T?) are strictly prohibited from being used as target types in patterns. Attempting to use a nullable value type in a pattern (e.g., obj switch { int? => ... } or expression is int? variableName) results in compiler error CS8116. Pattern matching evaluates the dynamic type of references or boxed values. While Nullable<T> is a standard, unboxed struct on the stack, boxing it invokes specific CLR behavior: it is never boxed as a Nullable<T>. Instead, it either becomes a null reference (if HasValue is false) or is boxed as the underlying non-nullable type T (if HasValue is true). To match a boxed nullable value type, the pattern must use the underlying type T.
  • Definite Assignment: When a variable is declared within a declaration pattern, C#‘s compiler flow analysis ensures the variable is only considered “definitely assigned” in code paths where the pattern explicitly evaluated to true.

Structural Implementations

The is Operator When used with the is operator, patterns act as boolean expressions. To use a C# 9.0 type pattern without a variable designation, it must be part of a logical pattern.
Switch Statements Type patterns serve as case labels within switch statements, allowing polymorphic routing based on runtime types.
Switch Expressions In C# 8.0+, type patterns form the arms of a switch expression, mapping types directly to evaluated return values.
Tired of Poor C# Skills? Fix That With Deep Grasping!Learn More