For the OP (that seems to be just starting on programming):
It is nice that you got an assignment to reduce the cyclomatic complexity of a method, and it is good both to know what is it and how to keep it low as a general practice.
However, try to not get too zealous with these kind of metrics. There is more value on having the code as straightforward as possible, easy to reason about and understand quickly, and only worry about metrics after profiling the app and knowing the places it matters the most.
For more experienced coders:
This simple problem reminded me of a very famous discussion from 1968 between Dijkstra and other fellas on the ACM periodic. Although I tend to align with him on this matter, that was one answer from Frank Rubin that is very reasonable.
Frank basically advocates that "elegance" can many times arise from code clarity, instead of any other metrics of practices. Back then, the discussion was the over-use of the goto statement on the popular languages of that time. Today, discussion goes around cyclomatic complexity, terseness, oop or whatever.
The bottom line is, in my opinion:
- know your tools
- code with clarity in mind
- try to write efficient code on the first pass, but don't overthink
- profile your code and decide where it's work to spend more time
Back to the question
The implementation presented in the question got the following scores in my Visual Studio Analyzer:
Cycl. Compl: 5; Maintainability: 67
The snippet presented by @Boris got this:
Cycl. Compl: 4; Maintainability: 68
Even though the cyclomatic complexity improved, the maintainability index keeps basically the same. Personally, I consider the latter metric more valuable most of the time.
Just for fun, let's see how a solution akin the one presented by Frank Rubin that uses the dreaded goto
statement would look like:
private bool MethodName() {
for (int k = 0; k < 8; k++) {
for (int j = 0; j < 3; j++) {
if (watheverTestCondition(k, j) is false) goto reject;
}
// condition is true for all items in this row
return true;
// if condition is false for any item, go straight to this line
reject:;
}
return false;
}
Honestly, I think this is the most clear, simple and performatic implementation for this. Do I recommend goto
in general as a code feature? NO. Does it fit perfectly and smoothly in this specific case? YES. And what about the metrics?
Cycl. Compl: 4; Maintainability: 70
Bonus
Just because I wouldn't be able to sleep if I didn't tell that, this is how you would implement this in real life:
obj.Any(row => row.All(watheverTestCondition));
Cycl. Compl: 1; Maintainability: 80