C# Regex Matches Example: How to Find All Pattern Occurrences in .NET
Use Regex.Matches from the System.Text.RegularExpressions namespace to return a MatchCollection containing every occurrence of a pattern in a string, then iterate over the collection to access each match's Value, Index, and captured groups.
The Regex.Matches method is essential for extracting multiple occurrences of patterns from text in C# applications. While the VS Code repository implements similar search functionality in TypeScript files such as src/vs/editor/common/model/textModel.ts, the underlying regex principles align with .NET's System.Text.RegularExpressions engine. This article provides practical C# regex Matches examples derived from real-world pattern matching scenarios.
What Is Regex.Matches in C#?
Regex.Matches is a static method that scans an input string for every substring that matches a regular expression pattern. Unlike Regex.Match, which stops after finding the first occurrence, Matches returns a MatchCollection containing all results. This collection exposes properties such as Count and allows enumeration to access individual Match objects with their Value, Index, and Length properties.
Because the method is static, you do not need to instantiate a Regex object for single-use scenarios. However, for high-frequency operations, compiling the pattern improves performance significantly.
Basic C# Regex Matches Example
The following example demonstrates how to find all four-letter words in a sentence using word boundaries.
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string input = "This sample text has many four word parts.";
string pattern = @"\b\w{4}\b"; // four-letter words
// Get all matches
MatchCollection matches = Regex.Matches(input, pattern);
Console.WriteLine($"Found {matches.Count} matches:");
foreach (Match m in matches)
{
// m.Value – the matched substring
// m.Index – start position in the original string
Console.WriteLine($"• \"{m.Value}\" at position {m.Index}");
}
}
}
Output:
Found 4 matches:
• "This" at position 0
• "text" at position 15
• "many" at position 25
• "four" at position 30
Advanced Pattern Matching Techniques
Case-Insensitive Matching with RegexOptions
To perform a case-insensitive search, pass RegexOptions.IgnoreCase as the third argument.
string input = "Apple, apple, APPLE, aPpLe";
string pattern = @"apple";
MatchCollection matches = Regex.Matches(
input,
pattern,
RegexOptions.IgnoreCase); // ignore case
Console.WriteLine($"Matches: {matches.Count}"); // → 5
Extracting Captured Groups from Matches
Use named capture groups to extract specific components from each match, such as year, month, and day from date strings.
string input = "2023-04-15 2023/04/16 2023.04.17";
string pattern = @"(?<year>\d{4})[-/.](?<month>\d{2})[-/.](?<day>\d{2})";
foreach (Match m in Regex.Matches(input, pattern))
{
Console.WriteLine(
$"Date: {m.Value} (Y:{m.Groups["year"].Value}, M:{m.Groups["month"].Value}, D:{m.Groups["day"].Value})");
}
Optimizing Performance with Compiled Regex
When calling Matches repeatedly inside a loop, compile the pattern once to avoid re-parsing the regex on every iteration.
Regex regex = new Regex(@"\b\w{4}\b", RegexOptions.Compiled);
for (int i = 0; i < 1000; i++)
{
var matches = regex.Matches(someLongString);
// …process matches…
}
VS Code Repository Regex Implementation References
Although VS Code is implemented in TypeScript, its search architecture relies on the same regex principles found in the .NET System.Text.RegularExpressions namespace. The following files demonstrate how large-scale applications handle pattern matching across text buffers:
| File Path | Description |
|---|---|
src/vs/editor/common/model/textModel.ts |
Contains the core text model used by the editor, including search APIs that rely on regex patterns to locate text within buffers. |
src/vs/workbench/services/search/common/search.ts |
Implements the "Find in Files" feature using JavaScript RegExp, showing how regexes are applied to large text buffers across workspaces. |
src/vs/workbench/services/search/test/common/replace.test.ts |
Unit tests illustrating how regex replace patterns are validated and executed within VS Code's search engine. |
src/vs/workbench/contrib/webview/browser/webviewFindAccessibilityHelp.ts |
Provides UI strings describing the "Regular Expression" option in the Find widget, demonstrating user-facing regex documentation. |
These references show that whether you are using C# Regex.Matches or JavaScript RegExp, the fundamental approach of iterating over match collections and handling pattern options remains consistent across languages.
Summary
Regex.Matchesreturns aMatchCollectioncontaining every occurrence of a pattern, unlikeRegex.Matchwhich stops at the first result.- Always import
System.Text.RegularExpressionsto access the method. - Access individual match properties such as
Value,Index, andLengthduring iteration. - Use
RegexOptions.IgnoreCasefor case-insensitive searches andRegexOptions.Compiledfor high-performance scenarios with repeated calls. - Extract structured data using named capture groups within your regex patterns.
Frequently Asked Questions
What is the difference between Regex.Match and Regex.Matches in C#?
Regex.Match returns a single Match object representing the first occurrence of a pattern and stops scanning immediately. Regex.Matches scans the entire input string and returns a MatchCollection containing every match found. Use Match when you only need the first result, and Matches when you need to process all occurrences.
How do I count the total number of matches using Regex.Matches?
The MatchCollection returned by Regex.Matches exposes a Count property that provides the total number of matches without requiring manual iteration. Simply access matches.Count after calling the method, as shown in the basic usage example.
Does Regex.Matches throw an exception if no matches are found?
No, Regex.Matches does not throw an exception when no matches are found. Instead, it returns a valid MatchCollection with a Count of zero. You can safely iterate over an empty collection using foreach or check if (matches.Count == 0) to handle cases where the pattern does not exist in the input string.
When should I use RegexOptions.Compiled with Regex.Matches?
Use RegexOptions.Compiled when you will execute the same regex pattern multiple times—such as inside a loop processing thousands of strings or when calling Matches repeatedly on different inputs. This option increases initial compilation overhead but significantly improves execution speed for subsequent matches by compiling the regex to MSIL. For single-use patterns, the standard static Regex.Matches call provides better startup performance without the compilation cost.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →