Writing patterns in C#
Use a verbatim string, @"\d+", so backslashes reach the regex engine unchanged; in a normal string you would need "\\d+". For a pattern with quotes, a raw string literal ("""...""") needs no escaping at all. Regex.Escape turns user input into a literal pattern.
What is different in .NET
- Unicode by default.
\d,\wand\smatch non-ASCII digits, letters and spaces. Use[0-9]orRegexOptions.ECMAScriptwhen you mean ASCII. - Lookbehind of any length, balancing groups, character class subtraction
[a-z-[aeiou]], RightToLeft and conditionals are .NET features that JavaScript and PCRE lack or limit. - No possessive quantifiers (
a++): use an atomic group(?>a+). - Named groups can be written
(?<name>...)or(?'name'...), and groups with the same name share captures. - Three engines. The default backtracking interpreter,
RegexOptions.Compiled(IL at run time) and[GeneratedRegex](C# at build time) behave the same;RegexOptions.NonBacktrackingguarantees linear time but has no lookarounds, backreferences, atomic groups or conditionals.
Performance
The static methods (Regex.IsMatch(input, pattern)) cache the last 15 patterns, so they are fine for occasional use. For a pattern used often, make it a [GeneratedRegex] partial method or property: no parsing at startup, and the generated code shows in your IDE. Regex.EnumerateMatches and Regex.Count work on spans without allocating Match objects.
FAQ
What regex syntax does C# use?
.NET's own flavor in System.Text.RegularExpressions: Perl-style syntax plus .NET additions such as balancing groups, variable-length lookbehind, character class subtraction and RightToLeft.
Why does \d match Arabic or Devanagari digits in .NET?
\d matches any Unicode decimal digit (category Nd). Use [0-9] or RegexOptions.ECMAScript to match only ASCII digits.
Why does ^\d+$ accept a trailing newline?
$ also matches before a final \n. Use \z to require the very end of the input.
How do I avoid catastrophic backtracking in .NET?
Pass a timeout (new Regex(pattern, options, TimeSpan.FromMilliseconds(100)) or matchTimeoutMilliseconds in [GeneratedRegex]), avoid nested quantifiers like (a+)+, or use RegexOptions.NonBacktracking, which runs in linear time.
What is [GeneratedRegex]?
A source generator attribute (.NET 7 and later) on a partial method or property that writes the matching code in C# at build time: no startup parsing, and it works with trimming and Native AOT.
Does .NET support possessive quantifiers?
No. Use an atomic group instead: (?>a+) never gives back what it matched.