Counting Lines of Code (LOC) is not as straightforward as it seems. Developers often wonder:
- Should method signature declarations count?
- What about lines with only braces
{
or}
? - If a method call spans multiple lines due to many parameters, is it counted as several lines?
- Do
namespace
declarations orusing
statements count? - Should interface or abstract method declarations be included?
- What about field assignments during declaration?
- Do blank lines count?
The answers vary depending on coding style and programming language (e.g., C#, VB.NET). This can lead to significant differences when measuring LOC.
Logical LOC vs. Physical LOC
Measuring LOC by parsing source files can be tricky, but there’s a simpler and more accurate approach: logical LOC.
Logical LOC has two main advantages over physical LOC:
- Independent of coding style:
The count remains the same, even if a method call spans multiple lines due to many arguments. - Language agnostic:
LOC from different languages (e.g., C#, VB.NET) can be compared and summed consistently.
How Logical LOC Works in .NET
In the .NET ecosystem, logical LOC can be calculated using PDB files. These files connect IL code to the original source code. Tools like NDepend calculate logical LOC by counting sequence points in the PDB file.
- Sequence points map IL code to specific locations in the source code.
- Sequence points for braces
{
and}
are ignored in this calculation.
LOC Calculation Examples
- For a method:
Logical LOC = Number of sequence points in the PDB file. - For a type, namespace, assembly, or application:
Logical LOC is the sum of LOC for its methods, types, namespaces, or assemblies, respectively.
Key Observations
- No LOC for declarations:
Interfaces, abstract methods, namespaces, fields, and method declarations have no sequence points, so they don’t count as LOC. - Field initialization:
Inline field initializations generate sequence points in the constructor (or static constructor for static fields). - Anonymous methods:
LOC for anonymous methods doesn’t affect the LOC of the declaring method. - IL instructions to LOC ratio:
The ratio of # IL instructions (NbILInstructions) to LOC in C# or VB.NET is usually around 7:1.
By focusing on logical LOC, you can measure executable code accurately and consistently across projects and languages.
Now you might want to read: Why Is Counting Lines of Code (LOC) Useful?
Lines of code in .NET (e.g. C#, VB.NET) is not as relevant as in high-level programming languages of decades ago.
Whatever language is used in .NET, it gets compiled to MSIL (Microsoft Intermediate Language). Many of the shortcuts we use in our .NET languages are compiled down to what it would be without the shortcut.
For example, the “using” statement for IDisposable object. It is a nice shorthand (with the one fault that constructor errors require the “using statement to be in a try-catch) but compiles to MSIL with try-catch-finally. So, the lines saved by using “using” really are not reduced in MSIL than if the developer simply used try-catch-finally (which is also a more versatile approach).
Instead, look for operational efficiencies that make a measurable difference in performance and thread safety. The number of lines of code is mostly irrelevant.