Statics and Generics

So statics are generally considered evil, the enemy of TDD and IOC, and at odds with the purity of OO design. Shame they’re so incredibly fast!

Whilst we’re talking about the TDD issue, I recommend you stop for a moment and go and take a look at the Fakes Framework added to VS11. Fakes is the successor, to Moles & Stubs, and it rather elegantly solves the statics testability problem, by introducing the concept of shims.

But statics do have their uses, especially when we’re talking about hyper critical performance situations. For example static member access is approx. 5-6% faster than instance members. But more importantly IOC or Dependency Injection itself are comparatively slow and frequently uses Reflection (often inappropriately). For some scenarios, like logging, statics are powerful tool – if used with eyes wide open. To be clear, you can say that about pretty much any programming paradigm.

Back to the purpose of this post though. After trying to clear up a bit of the mud slung at statics (and at the risk of starting a flame war anywhere). Let’s talk about the greater evil of statics with generics. These things are so evil that ReSharper (the tool you must install if you spend any time developing in .NET) gives you a nice little squiggle and warning –

image

Clearly we’re talking about a great evil here!

ReSharper is right to warn you about this as it’s a real issue for new developers to understand what’s going on. Going back to your old lectures – a “Class is a definition of an object, and object is an instantiation of a class”. In C# you cannot instantiate a generic class, actually more accurately you cannot instantiate an open generic class. Now when you Google this be sure to use “open generic type” as that’s what everyone uses although in C# only classes and interfaces can be generic (a type describes pretty much every language element, including enums, structs, value types, delegates, generic arguments, etc.), and only classes can be instantiated (interfaces are implemented).

So what is an open generic class? It is a class where any of the generic arguments are not yet specified. The generic argument in our example is ‘T’ (as in Bag;).

To instantiate a generic class, you must first close it, that is fully specify it’s generic arguments. In code this is normally done when you instantiate it, e.g. {csharp decode=”true”}Bag<T> intBag = new Bag<T>();{/csharp}.  As you can see the we specify that the type T should in fact be of type ‘int’ for the ‘intBag’ instance of our generic Bag class. So what’s the problem? Well in closing a generic class you create a new type ‘Bag’ which is the closed generic class made from the ‘Bag’ open generic class, it is a class in it’s own right, and critically, it has it’s own independent statics. To the unwary this can appear counter intuitive, as they might expect that the static is shared across all instances of ‘Bag’ or it’s descendants, however Bag doesn’t have either and ‘Bag’ is not strictly a descendent.

So are all statics in generic types evil? Well let’s expand out our view a little –

image

– for some reason ReSharper isn’t complaining about our new field ‘_thisIsOk’. The reason is simple, as the field itself is a generic and uses the generic argument of the encapsulating class it’s unlikely you are going to get confused over the field’s scope, unlike with ‘_bagCount’.

Should we just ban statics in generics and be done with it (easier said than done)? Well the answer to that is complex, but there are some really good examples of where it is very useful, some of which I’ll show you in future posts, the important thing is to remember that the static is only global to the closed generic type. In our example ‘_bagCount’ will only be global to ‘Bag’, a ‘Bag’ will have it’s own ‘_bagCount’ static. When you understand the limitation, you can also understand it’s usefulness.

Which brings us to the bit on which so many developers get stuck – how do I have a static shared across all types of my generic class? Well there are two ways really, the best way (if you ask me) is the base class model, for example –

This is the most elegant solution, but a base class is not always a viable option (you may need to descend from a different class already. In that case you can use a holder class like so –

– which is far less elegant, although declaring the holder as internal at least means it’s not accessible outside the current assembly.

I plan on following up with far more in-depth examples, and apologise if this one is a little ‘basic’ but I wanted to get some groundwork done before I delve deeper into the .NET framework, and Reflection.

Comments 5

  • Are statics evil? In OO code certainly, you obviously agree due to the defensive opening paragraph ;). It is as important that engineers get their design right and their code robust and readable rather than chase performance enhancements that may/will never be realised.

    I mean, if you’re going to start leaving what are essentially globals everywhere then why use C# at all? Surely there are more suited languages and paradigms (can you say functional programming?). I concede I’m taking an extreme stance but it’s something to consider.

    I’ll leave on a positive by saying having seen first hand the performance enhancements that can be gained make the above examples very powerful, just remember that with great power comes great responsibility.

    • Hi Rob,

      I agree that fundamentally statics are similar to globals (though their scope and visibility is far more controllable so they are clearly not pure globals), and they clearly break true OO design principles. There are other examples of non-OO elements in C#, for example lambdas are clearly functional, and expression trees are dynamic. Attributes can be thought of as a primitive form of AOP.

      I think the mistake is to assume C# is purely an OO language, when really it is a programming language. Like it’s predecessors there is a certain acknowledgement of the need for performance, and that leaks into elements of a number of methodologies appearing throughout the language. In the end it’s all about right tool for the job in hand, and certainly one example where statics excel is performance.

      But should you use statics? I’d agree that in general you should avoid them like the plague; but if you do use them, do so with eyes wide open.

  • […] first blog post concentrates on statics and generics, laying the ground work before intending to delve deeper into […]

  • […] first blog post concentrates on statics and generics, laying the ground work before intending to delve deeper into […]

  • […] created?  Well it’s created in a static constructor, and here comes a great example of where statics are useful.  Because it’s in the static constructor it will be called once (and only once) whenever the […]

Leave a Reply

%d bloggers like this: