How many times does the letter "a" appear in the word "abracadabra"? Solving the problem in C#
Imagine: you are writing a log analyzer, parsing a CSV file, or simply checking how many times a user entered the @ symbol in an email. The task "count the number of occurrences of a character or substring in a string" is one of those that appears in every other project. On Stack Overflow, this question has gathered thousands of views and dozens of answer options. Not surprisingly: in C# there are at least 5 different ways, and choosing the right one can save hours of debugging.
In this article, we will break down all the popular methods — from the classic loop to modern Span<T> and LINQ. You will learn which method is faster, which is more readable, and which is better not to use in production. Let's go!
1. Classic foreach loop — the old-school method
The most intuitive way: take a string, iterate through each character, and count matches. It always works and requires no additional libraries.
string text = "abracadabra";char target = 'a';int count = 0;
foreach (char c in text){ if (c == target) count++;}
Console.WriteLine($"The character '{target}' appears {count} time(s)."); // Output: 4Pros: readability, control over the process, you can add logic (e.g., ignore case).
Cons: not suitable for counting substrings (multiple consecutive characters) — for that you would need to write a nested loop.
2. Count() method from LINQ — a one-liner for characters
If you like concise code and use LINQ, this option is for you. The Count() method takes a predicate and returns the number of elements that satisfy the condition.
using System.Linq;
string text = "Hello, World!";char target = 'l';
int count = text.Count(c => c == target);Console.WriteLine(count); // Output: 3Note: Count() is an extension method from the System.Linq namespace. If you haven't added using System.Linq, the code will not compile.
This method is not directly suitable for counting a substring. You would first need to split the string or use regular expressions (see section 5).
3. Span<T> and MemoryExtensions — maximum performance
If you work with large strings (megabytes of logs) and every millisecond counts, forget about LINQ. Use Span<char> and the Count() method from MemoryExtensions (available from .NET 5+).
using System;
string text = "abracadabra";ReadOnlySpan<char> span = text.AsSpan();int count = span.Count('a');
Console.WriteLine(count); // Output: 4Why is this fast? Span<T> works with contiguous blocks of memory without allocating new objects. The Count() method in MemoryExtensions is optimized for SIMD instructions — it processes 16-32 characters per CPU cycle.
There is also a solution for substrings:
int count = span.Count("ra"); // counts occurrences of the substring "ra"Console.WriteLine(count); // Output: 2 ("abracadabra" contains "ra" twice)Important: this method is case-sensitive. If you need to ignore case, first convert the string to one case or use span.Count("ra", StringComparison.OrdinalIgnoreCase).
4. Split method — a clever trick for substrings
An old but working method: split the string by the target substring and count the number of parts minus one.
string text = "one, two, three, one, four";string target = "one";
int count = text.Split(target, StringSplitOptions.None).Length - 1;Console.WriteLine(count); // Output: 2How it works: Split