Static Initializers in C#: A Cautionary Tale

I have been chasing a weird bug in a solution I’ve been working on. The insight on how certain C# feature work by design, which I got after catching of the culprit, made me write this post in the hope that somebody can save hours or days of debugging.

My solution uses SPMeta2 library to define a structure of a SharePoint site to be provisioned. You specify a collection of “nodes” that represent your lists, content types, site columns and so on. It can be then “provisioned” on the target side using CSOM or SSOM.

Static Function (yes, it’s PHP but it gets the point, right?)

The structure was defined using static properties on static classes such as FieldDefinitions.cs or ContentTypeDefinitions.cs. A new content type, for instance, would be defined as a ContentTypeDefinition property initialized inline with a static initializer.

        public static ContentTypeDefinition BaseContentType = new ContentTypeDefinition()
        {
            Name = "BaseContentType",
            Id = new Guid("EC0463EA-2AA1-4461-8407-2A4D0FD58B8B"),
            ParentContentTypeId = BuiltInContentTypeId.Document,
            Group = GroupNames.MyContentTypeGroupName
        };

However, when I retrieved a template (a sum of all ModelNodes in the definition) I would get a weird System.TypeInitializationException in the nodes collection.

The source of my headache for a couple of days (simplified)

I spent a couple of days trying to find the root of the issue. As I couldn’t debug static initializers, I had to rely on removing and adding nodes to see what triggers the error. Finally I got it.

The offending code was like this:

public static class ContentTypeDefinitions 
{
        public static ContentTypeDefinition ContentType1 = new ContentTypeDefinition()
        {
            Name = "ContentType1",
            ...
            ParentContentTypeId = ContentTypeDefinitions.ContentType2.Id
        };

        public static ContentTypeDefinition ContentType2 = new ContentTypeDefinition()
        {
            Name = "ContentType2",
            ...
            ParentContentTypeId = BuiltInContentTypeId.Document
        };
...
}

Do you see the error?

ContentType1 (a static field) relies on the ContentType2 definition (another static field) to be initialized. However, ContentType2 is defined AFTER the ContentType1 in the source code. But, since when the order of definitions in C# is important? Shouldn’t the strongly-typed nature of C# make it irrelevant?

As per C# specifications, section 10.11 Static Constructors says:

If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor.

C# 1.2 Language Specification, section 10.11 paragraph 7.

I fixed the code just by reordering the static fields:

public static class ContentTypeDefinitions 
{
        public static ContentTypeDefinition ContentType2 = new ContentTypeDefinition()
        {
            Name = "ContentType2",
            ...
            ParentContentTypeId = BuiltInContentTypeId.Document
        };

        public static ContentTypeDefinition ContentType1 = new ContentTypeDefinition()
        {
            Name = "ContentType1",
            ...
            ParentContentTypeId = ContentTypeDefinitions.ContentType2.Id
        };

...
}

And it just works.

If you want to see it by yourself, this is a minimal demo that makes the error. You can run it inside DotNetFiddle.

As soon as the order of static fields is reversed, it works.

Playing with NDepend

Few days ago I used NDepend tool to analyze the code of one of our bigger projects in Sogeti. Here are my thoughts on the tool.

NDepend is a static dependency analyzer tool. It scans your compiled code, the PDBs and the source code and produces a “map” of your code dependencies, metrics and structures. It has been around for several years now, and it has kept beeing better in every new edition.

The default view of NDepend is the so-called “Report” that highlights all the potential issues with your code. It gives you a trove of information to optimize your code, in a HTML format that’s easy to share. The report contains the summary of all the main features of the tool: rule violations, dependency cycles, complex code and so on.

NDepend Report

The next feature that I used is the dependency visualization. There are two “flavours” to it: the dependency graph and the dependency matrix.

The dependency graph is easy to grasp but it can only be meaningfully used with a handful of classes and namespaces. It quickly becomes a mess with more than a couple of dozen objects.

NDepend Dependency Graph

The dependency matrix is a much more powerful tool. It can be used to spot dependency cycles, infrastructure classes, “god” classes, cohesion and coupling and so on. However, it’s not as intuitive to analyze as the graph, it takes some time playing with it to grasp the information without consulting the help windows.

NDepend Dependency Matrix

NDepend has a full set of code complexity and maintainibility rules. It can quickly highlight the most important issues so that you can concentrate on fixing the most critical parts of your code.

NDepend Code Rules

But it’s just the surface of it. NDepend has a full-blown language called CQLinq, akin to SQL, that allows you to query your code. You can find classes that have high coupling, methods that are too complex, nested structures in the code and a myriad of other code patterns.

NDepend CQLinq

In my opinion, NDepend is an invaluable tool if you’re concerned about your code quality (and you should be). It takes some time to grasp and master all the power of it, as it can be an overwhelming experience for a first-time user, but it’s a time well invested.

Thanks to Patrick Smacchia (the main force behind NDepend) for the NDepend license for MVPs, that allowed me to fully evaluate the tool.