Skip to main content
The constant pattern in C# is a pattern matching construct used to test whether a given expression evaluates to a specific, compile-time constant value. Semantically, the pattern evaluates to true if object.Equals(constant, expression) returns true, providing a type-safe equality check between the runtime value of the expression and the specified constant.

Allowed Constant Expressions

The pattern requires the right-hand side of the match to be a compile-time constant. Valid constant expressions include:
  • Numeric literals (int, float, double, etc.)
  • Character and string literals ('A', "Text")
  • Boolean literals (true, false)
  • Enum values
  • Declared const fields
  • The null keyword
  • default value expressions (e.g., default(T))

Syntax

The constant pattern is primarily implemented using the is operator or within switch statements and switch expressions.

Execution Semantics and Equality Resolution

The C# language specification strictly defines the semantics of the constant pattern as matching if object.Equals(constant, expression) evaluates to true. However, the compiler applies specific rules for type safety, implicit conversions, and Intermediate Language (IL) optimizations:
  • Implicit Conversions: When matching primitive numeric types, the constant value must be implicitly convertible to the type of the input expression. If no implicit conversion exists from the constant’s type to the expression’s type, the compiler generates an error.
  • IL Optimizations: While the semantic definition relies on object.Equals, the compiler optimizes the emitted IL based on the operand types to avoid boxing overhead where possible:
    • Primitive Numerics and Enums: The compiler avoids calling object.Equals. For boxed primitives, it emits an isinst type check, unboxes the value, and performs a direct value comparison (e.g., the ceq instruction).
    • Complex Value Types: For types like decimal or custom structs (e.g., matching against default(MyStruct)), the compiler cannot use a simple ceq instruction. It emits calls to decimal.Equals, decimal.op_Equality, IEquatable<T>.Equals, or object.Equals to ensure correct semantic evaluation.
    • Strings: The compiler emits a call to string.Equals.
  • Floating-Point NaN: Because the constant pattern adheres to object.Equals semantics, it handles NaN (Not-a-Number) values differently than the standard IEEE 754 equality rules applied by the == operator. While x == double.NaN always evaluates to false, the pattern x is double.NaN evaluates to true if the runtime value of x is NaN.
  • Null Checking: The null constant pattern (expr is null) is a specialized form optimized to a direct reference equality check against null. It strictly bypasses any overloaded == operators on the type to guarantee an accurate, un-hijackable null check (equivalent to object.ReferenceEquals(expr, null)).
Tired of Poor C# Skills? Fix That With Deep Grasping!Learn More