NDepend Blog

Improve your .NET code quality with NDepend

Cyclomatic Complexity in C#: Everything You Need to Know

October 21, 2024 3 minutes read
Cyclomatic Complexity in C#
Cyclomatic complexity is a code metric used to measure the complexity of a program’s control flow. In C#, it represents the number of independent execution paths through the code of a method, often determined by branching structures like if-else statements, loops, and switch cases. The higher the Cyclomatic Complexity, the more difficult the code is to understand, test, and maintain. Lower complexity indicates simpler, more readable code.

Definition of Cyclomatic Complexity in C#

The Cyclomatic Complexity for a C# method is concretely 1 + {the number of following expressions found in the body of the method}:

The following expressions are not counted for CC computation:

Example of Cyclomatic Complexity Impact in C#

Exhibiting a Complex Method

Here is a complex method with entangled if and else scopes. The keyword if is used six times and && is used once. Hence its Cyclomatic Complexity score is 8:

Refactoring the Complex Method in Several Simpler Methods

The method above can be refactored into several less complex methods. In the code we use CC to refer to each method Cyclomatic Complexity score:

Benefits of Refactoring:

  • Simpler Control Flow: The main method now delegates specific tasks to smaller, more focused methods.
  • Easier to Test: You can test each smaller method independently.
  • Lower Cyclomatic Complexity: The complexity is spread across multiple methods, making each method easier to understand and maintain independantly.

Measuring Cyclomatic Complexity in C#

You can’t improve what you don’t measure, so using a tool to evaluate code complexity is essential. Calculating this metric helps developers identify areas that might need refactoring to improve code quality
NDepend is a great option for this, as it measures the cyclomatic complexity of methods in C# code. For instance, it includes the Search Methods by Complexity feature, which helps identify complex methods for further analysis.

Ruling C# Cyclomatic Complexity

NDepend offers several rules like Avoid methods too big, too complex that flag methods with excessively high Cyclomatic Complexity scores, highlighting potential issues in the code.

You are probably working with a large legacy codebase, making it impractical to refactor every complex method. This is why it’s essential to measure Cyclomatic Complexity against a baseline, allowing you to focus on new or refactored methods that are too complex. There are two rules for that:

Visualizing C# Cyclomatic Complexity

A colored treemap can be used to visualize the cyclomatic complexity of your C# methods. In this visualization, each rectangle represents a method:
  • The size of the rectangle corresponds to the number of statements in the method.
  • The color of the rectangle reflects the method’s cyclomatic complexity.
NDepend Visualize C# Cyclomatic Complexity

C# Cyclomatic Complexity and Tests

Writing tests for your code is nowadays an essential practice for every professional C# developer. Typically, a test covers a single execution path, while the Cyclomatic Complexity score of a method represents the number of independent execution paths. Therefore, Cyclomatic Complexity provides a rough estimate of how many tests are required to fully test a method.

By running tests, you can determine the code coverage for each method. A method partially covered means that not all its independent execution paths are challenged by tests. The rule Methods should have a low C.R.A.P score spots methods that both have high Cyclomatic Complexity scores and are poorly tested (C.R.A.P stands for Change Risk Analyzer and Predictor). The matched methods clearly indicate pain points in your code and should be tested and refactored.

NDepend C# Cyclomatic Complexity and Code Coverage

Conclusion

In conclusion, understanding Cyclomatic Complexity in C# is essential for maintaining code quality and managing technical debt. By measuring this complexity with a tool like NDepend, developers can identify areas that require attention and improve the overall robustness of their applications. Emphasizing simplicity and clarity in code will lead to more maintainable and efficient software in the long run.