What Cyclomatic Complexity Is Too High? Thresholds, Examples, and Fixes
Cyclomatic complexity is one of the oldest code metrics and still one of the most useful: it tells you how many independent paths run through a method, and therefore roughly how many test cases you need to cover it. The common question is where to draw the line. This guide explains how the number is calculated, the thresholds most teams use, and how to reduce it in a real C# method.
How cyclomatic complexity is calculated
The McCabe-style count most tools use starts at 1 for the method and adds 1 for each decision point.
- if and else if
- for, foreach, while, and do loops
- each case label in a switch
- catch clauses
- the ternary operator ?:
- each && and || in a condition
Worked example
public int CountOverdue(Customer customer)
{
var count = 0;
if (customer != null && customer.IsActive) // +1 if, +1 &&
{
try
{
foreach (var invoice in customer.Invoices) // +1
{
if (invoice.DueDate < DateTime.UtcNow) // +1
count++;
}
}
catch (InvalidOperationException) // +1
{
_logger.LogWarning("Invoice list changed during count");
}
}
return count;
}
So what number is too high?
Ten is the threshold McCabe originally proposed and the default in many tools, including CodeInspector. Some teams allow 15 for orchestration code. What matters more than the exact number is consistency: pick a limit, flag new code that exceeds it, and work existing hotspots down over time.
- 1–10: simple and easy to test — the usual target
- 11–20: moderately complex — review it, and refactor if it keeps changing
- 21–50: hard to understand and test — refactor before adding features
- 50+: very high risk — effectively untestable as written
How to reduce cyclomatic complexity
Our guide to reducing nested if statements walks through these patterns with before-and-after code.
- Use guard clauses to exit early instead of nesting conditions
- Extract each branch of a large if-else or switch into a well-named method
- Replace type or status switches with a dictionary or polymorphism
- Move complex boolean conditions into named methods (IsEligibleForDiscount)
- Split methods that do several jobs — validation, calculation, persistence — into separate steps
Measuring complexity across a C# repository
The free C# code quality checker on our tools page calculates per-method cyclomatic complexity for a pasted snippet and flags anything above 10. For a whole repository, a CodeInspector scan flags long C# methods (CI0007) — usually where complexity concentrates — and reports excessive complexity directly in C++ code, so you can find hotspots by file and then check individual methods in the free tool.
Frequently asked questions
Is cyclomatic complexity the same as cognitive complexity? No. Cyclomatic complexity counts paths; cognitive complexity tries to measure how hard code is to read and penalises nesting more heavily. Both are useful.
Does a switch with many cases always need refactoring? Not always — a flat switch that maps values is easy to read even with a high count. Use judgement, or replace it with a lookup table.
Does high complexity mean the code is buggy? It means the code is harder to test fully, which makes bugs more likely to survive.