Question
How can I count how many times a character or substring appears inside a string in C#?
For example, I want to count how many / characters exist in a string. I know there are several ways to do this, but I am not sure which approach is the best or simplest.
One approach I am currently using is:
string source = "/once/upon/a/time/";
int count = source.Length - source.Replace("/", "").Length;
For substrings with length greater than 1, I am using:
string haystack = "/once/upon/a/time";
string needle = "/";
int needleCount = (haystack.Length - haystack.Replace(needle, "").Length) / needle.Length;
Is this a good way to count occurrences, or is there a better or more readable approach?
Short Answer
By the end of this page, you will understand how to count the number of times a character or substring appears in a string in C#. You will learn simple approaches using Replace, loops, LINQ, and substring searching, plus when each option is appropriate.
Concept
In C#, counting occurrences in a string means checking how many times a specific value appears inside a larger piece of text.
This value can be:
- a single character, such as
'/' - a substring, such as
"cat"
This matters because string processing is common in real programs. Developers often need to:
- count separators in file paths or URLs
- count words or tokens in input text
- validate data formats
- inspect logs or API responses
- parse structured text
A string in C# is immutable, which means methods like Replace do not change the original string. Instead, they create a new string. That is why this technique works:
int count = source.Length - source.Replace("/", "").Length;
The code removes all / characters, compares the old and new lengths, and uses the difference as the count.
This is clever and short, but it is not always the clearest or most efficient option, especially for longer strings or repeated operations. For single-character counting, a loop or LINQ is often easier to read. For substring counting, searching with IndexOf in a loop is usually a better general solution.
The main idea is:
- Character counting: inspect each character and compare it
- Substring counting: search for the target repeatedly until no more matches are found
Mental Model
Imagine a string as a long row of tiles.
- If you want to count a character, you walk across the tiles one by one and count every tile that matches.
- If you want to count a substring, you slide a small pattern across the row and check where it fits.
Another way to think about Replace is this:
- Start with a rope of a certain length
- Cut out every
/ - Measure the rope again
- The missing length tells you how many characters were removed
That works well for simple counting, but if you want more control, walking through the string directly is often easier to understand.
Syntax and Examples
1. Count a single character with a loop
string source = "/once/upon/a/time/";
int count = 0;
foreach (char c in source)
{
if (c == '/')
{
count++;
}
}
Console.WriteLine(count); // 4
This is beginner-friendly and very readable:
- loop through each character
- compare it to
'/' - increase the counter when it matches
2. Count a single character with LINQ
using System.Linq;
string source = "/once/upon/a/time/";
int count = source.Count(c => c == '/');
Console.WriteLine(count); // 4
This is short and expressive. It works well when you already use LINQ.
3. Count a substring with Replace
string haystack = "abc--def--ghi--";
string needle = "--";
int count = (haystack.Length - haystack.Replace(needle, ).Length) / needle.Length;
Console.WriteLine(count);
Step by Step Execution
Consider this example:
string text = "/a/b/c/";
int count = 0;
foreach (char c in text)
{
if (c == '/')
{
count++;
}
}
Step by step:
textis"/a/b/c/"countstarts at0- The loop reads the first character:
'/'- it matches
countbecomes1
- The loop reads
'a'- no match
countstays1
- The loop reads
'/'- match
countbecomes2
- The loop reads
Real World Use Cases
Counting characters and substrings appears in many practical tasks:
- URL parsing: count
/characters to estimate path depth - CSV or log processing: count separators like commas, tabs, or pipes
- Validation: ensure a format contains the expected number of delimiters
- Text analysis: count words, tags, mentions, or repeated markers
- Configuration parsing: count
=or:characters in key-value data - Chat and moderation tools: count forbidden words or repeated patterns
- File handling: count directory separators in paths
Example: validating a simple date format like yyyy-mm-dd
string input = "2026-06-10";
int dashCount = input.Count(c => c == '-');
if (dashCount != 2)
{
Console.WriteLine("Invalid date format");
}
Example: counting occurrences of an error label in logs
string log = "INFO... ERROR... INFO... ERROR...";
string token = "ERROR";
int count = 0;
int index = ;
((index = log.IndexOf(token, index)) != )
{
count++;
index += token.Length;
}
Console.WriteLine(count);
Real Codebase Usage
In real codebases, developers usually choose the approach based on what they need:
For a single character
A loop or LINQ is common:
int slashCount = path.Count(c => c == '/');
This is readable and easy to maintain.
For a substring
IndexOf in a loop is a common pattern because it is explicit and flexible:
public static int CountOccurrences(string text, string value)
{
if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(value))
{
return 0;
}
int count = 0;
int index = 0;
while ((index = text.IndexOf(value, index, StringComparison.Ordinal)) != -1)
{
count++;
index += value.Length;
}
return count;
}
Common patterns in production code
Common Mistakes
1. Forgetting the difference between char and string
A character uses single quotes:
'/'
A string uses double quotes:
"/"
Broken example:
if (c == "/") // wrong
{
}
Correct:
if (c == '/')
{
}
2. Dividing incorrectly when using Replace for substrings
If the substring has length greater than 1, you must divide by needle.Length.
Broken:
string text = "abc--def--";
string needle = "--";
int count = text.Length - text.Replace(needle, "").Length; // wrong result
Correct:
Comparisons
| Approach | Best for | Readability | Handles substrings | Handles overlapping | Notes |
|---|---|---|---|---|---|
Replace length difference | Quick counting | High | Yes | No | Short, but creates a new string |
foreach loop | Single characters | Very high | No | No | Great for beginners |
LINQ Count | Single characters | High | No | No | Concise, needs System.Linq |
Cheat Sheet
Count a single character
int count = text.Count(c => c == '/');
or
int count = 0;
foreach (char c in text)
{
if (c == '/') count++;
}
Count a substring with Replace
int count = (text.Length - text.Replace(value, "").Length) / value.Length;
Count a substring with IndexOf
int count = 0;
int index = 0;
while ((index = text.IndexOf(value, index, StringComparison.Ordinal)) != -1)
{
count++;
index += value.Length;
}
Count overlapping substrings
int count = ;
index = ;
((index = text.IndexOf(, index, StringComparison.Ordinal)) != )
{
count++;
index += ;
}
FAQ
What is the easiest way to count a character in a string in C#?
For a single character, a foreach loop or text.Count(c => c == '/') is usually the easiest to read.
Is using Replace to count occurrences valid in C#?
Yes. It works for many cases, especially simple one-off tasks. However, it creates a new string, so it is not always the clearest or most efficient choice.
How do I count a substring instead of a single character?
Use IndexOf in a loop or the Replace length-difference method divided by the substring length.
How do I count overlapping substring matches in C#?
Use IndexOf in a loop and increase the index by 1 after each match instead of needle.Length.
Should I use LINQ to count characters?
LINQ is a good option when you want concise code and are already using LINQ. A loop is still perfectly fine and often easier for beginners.
Does string counting handle case sensitivity automatically?
No. If case sensitivity matters, use methods like IndexOf with StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase.
Mini Project
Description
Build a small C# utility that counts how many times a character or substring appears in text. This is useful in log analysis, input validation, and simple text processing tools. The project demonstrates both character counting and substring counting in a practical reusable form.
Goal
Create a reusable set of methods that can count characters, count non-overlapping substrings, and count overlapping substrings.
Requirements
- Create one method to count a single character in a string.
- Create one method to count non-overlapping substring matches.
- Create one method to count overlapping substring matches.
- Return
0fornull, empty text, or empty search values where appropriate. - Print example results using sample input strings.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.