Improve your .NET code quality with NDepend

log4net vs NLog A Comparison of How They Affect Codebases

Log4net vs NLog: A Comparison of How They Affect Codebases

Ah, the old “versus” Google search.  Invariably, you’re in the research stage of some decision when you type this word into a search engine.  Probably not something like Coke vs Pepsi.  Maybe “C# vs Java for enterprise projects” or “angular vs react.”  Or if you landed here, perhaps you’re looking at “log4net vs NLog.”

With a search like this, you expect a certain standard script.  The writer should describe each one anecdotally, perhaps with a history.  Then comes the matrix with a list of features and checks and exes for each one, followed by a sober list of strengths and weaknesses.  Then, with a flourish, I should finish with a soggy conclusion that it really depends on your needs, but I maybe kinda sorta like one better.

I’m not going to do any of that. Continue reading Log4net vs NLog: A Comparison of How They Affect Codebases

NDepend and .NET Fx v4.7.2: an extension method collision and how to solve it easily

In Oct 2017 I wrote about the potential collision problem with extension methods. At that time the .NET Framework 4.7.1 was just released with this new extension method that is colliding with our own NDepend.API Append() extension method with same signature.

The problem was solved easily because just one default rule consumed our Append() extension method, we just had to refactor this method to use it as a static method call instead of an extension method call:  ExtensionMethodsEnumerable.Append(...)


Unfortunately with the recent release of .NET Framework 4.7.2, the same problem just happened again, this time with this extension method:

This time 22 default code rules are relying on our ToHashSet() extension method. This method is used widely because it is often the cornerstone to improve significantly performances. But this means that after installing the .NET Fx v4.7.2, 22 default rules will break.

This time the problem is not solved easily by calling our ExtensionMethodsSet.ToHashSet<TSource>(this IEnumerable<TSource>)  extension method as a static method because in most of these 22 rules source code, changing the extension method call into a static method call require a few brain cycle. Moreover it makes the rules source code less readable: For example the first needs to be transformed into the second:

We wanted a straightforward and clean way for NDepend users to solve this issue on all their default-or-custom code rules.  The solution is the new extension method ToHashSetEx().

Solving the issue on an existing NDepend deployment is now as simple as replacing .ToHashSet()  with  .ToHashSetEx()  in all textual files that contain the user code rules and code queries (the files with extension .ndproj and .ndrules).

We just released NDepend v2018.1.1 with this new extension method  ExtensionMethodsSet.ToHashSetEx<TSource>(this IEnumerable<TSource>). Of course all default rules and generated queries now rely on ToHashSetEx() and also a smart error message is now shown to the user in such situation:

We hesitated between ToHashSetEx() and ToHashSet2() but we are confident that this problem won’t scale (more explanation on suffixing a class or method name with Ex here).


Actually we could have detected this particular problem earlier in October 2017 because Microsoft claimed that the .NET Fx will ultimately support .NET Standard 2.0 and  .NET Standard 2.0 already presented this ToHashSet() extension method. So this time we analyzed both C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\netstandard.dll and NDepend.API.dll to double-check with this code query that there is no more risk of extension method collision:

We find back both Append() and ToHashSet() collisions and since NDepend.API is not concerned with queryable, there is no more risk of collision:



Quickly assess your .NET code compliance with .NET Standard

Yesterday evening I had an interesting discussion about the feasibility of migrating parts of the NDepend code to .NET Standard to ultimately run it on .NET Core. We’re not yet there but this might make sense to run at least the code analysis on non Windows platform, especially for NDepend clones CppDepend (for C++), JArchitect (for Java) and others to come.

Then I went to sleep (as every developers know the brain is coding hard while sleeping), then this morning I went for an early morning jogging and it stroke me: NDepend is the perfect tool to  assess some .NET code compliance to .NET Standard, or to any other libraries actually! As soon on my machine I did a proof of concept in a few minutes, then spent half an hour to fix an unexpected difficulty (explained below) and then it worked.

The key is that .NET standard 2.0 types are all packet in a single assemblies netstandard.dll v2.0 that can be found under C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319 (on my machine). All these 2,334 types are actually type forward definitions and NDepend handles well this peculiarity. A quick analyze of netstandard.dll with NDepend with this quick code query makes it all clear: 

(Btw, I am sure that if you read this  you have an understanding of what is .NET Standard but if anything is still unclear, I invite you to read this great article by my friend Laurent Bugnion wrote 3 days ago A Brief History of .NET Standard)

.NET Standard Forwarded Types

Given that, what stoke me this morning is that to analyze some .NET code compliance to .NET Standard, I’d just have to include netstandard.dll in the list of my application assemblies and write a code query that  filters the dependencies the way I want. Of course to proof test this idea I wanted to explore the NDepend code base compliance to .NET Standard:

NetStandard assembly included in the NDepend assemblies to analyze

The code query was pretty straightforward to write. It is written in a way that:

  • it is easy to use to analyze compliance with any other library than .NET standard,
  • it is easy to explore the compliance and the non-compliance with a library in a comprehensive way, thanks to the NDepend code query result browsing facilities,
  • it is easy to refactor the query for querying more, for example below I refactor it to assess the usage of third-party non .NET Standard compliant code

The result looks like that and IMHO it is pretty interesting. For example we can see at a glance that NDepend.API is almost full compliant with .NET standard except for the usage of System.Drawing.Image (all the 1 type are the Image type actually) and for the usage of code contracts.

NDepend code base compliance with .NET standard

For a more intuitive assessment of the compliance to .NET Standard we can use the metric view, that highlights the code elements matched by the currently edited code query.

  • Unsurprisingly NDepend.UI is not compliant at all,
  • portions of NDepend.Core non compliant to .NET Standard are well defined (and I know it is mostly because of some UI code here too, that we consider Core because it is re-usable in a variety of situations).

With this information it’d be much easier to plan a major refactoring to segregate .NET standard compliant code from the non-compliant one, especially to anticipate hot spots that will be painful to refactor.

Treemap view of the compliance with .NET Standard

A quick word about the unexpected difficulty I stumbled on. Since netstandard.dll contains only type forward definitions, it doesn’t contain nested type. Concretely it contains List<T> but not List<T>+Enumerator (that is also part of the formal .NET Standard). Of course we don’t want to flag methods that use List<T>+Enumerator as non-compliant. To see the way we solved that, have a look at the tricky part in the code code query related to: allNetStandardNestedTypes

The code query to assess compliancy can be refactored at whim. For example I found it interesting to see which non-compliant third-party code elements were the most used. So I refactored the query this way:

Without surprise UI code that is non .NET Standard compliant popups first:

.NET Standard non-compliant third-party code usage

There is no limit to refactor this query to your own need, like assessing usage of non-compliant code — except UI code– for example, or assessing the usage of code non compliant to ASP.NET Core 2 (by changing the library).

Hope you’ll find this content useful to plan your migration to .NET Core and .NET Standard!