Why I don't like the GAC

A real example of why I don’t like the GAC in .NET:

I’m in the middle of restructuring the CruiseControl.NET build file. I create a new build, test it and its fine. I setup a new CruiseControl instance for a project I’m working on, and that’s fine too. I then copy this instance on to the build server and it fails with a TypeLoadException.

Stripping this down, I have an application that runs on one machine, but if I copy it file-for-file onto another machine it doesn’t run. This is the kind of thing that makes the control-freak side of me’s blood boil.

My next thought is ‘so what’s different between the 2 machines?’ The only thing that effects a .NET application’s assembly load routine outside of the local directory, app configuration (which we don’t do in CCNet) and programmatic assembly loading (which we don’t do either) is the GAC. So I look in machine number 1’s GAC and I see a copy of NUnit in there. ‘Hmmm’ (I think), ‘I wonder if that’s it’ (in theory if my build had gone against the version of NUnit in the GAC vs. the directory-local one I thought I’d specified there could be a problem). So I (eventually) manage to get NUnit out of my GAC, recompile CCNet, try again and everything’s hunky-dory.

So what is the point of all this? In my mind the GAC breaks the completeness / isolation concept for building and running an application in an environment. In my mind, I should be able to zip-up an application (as much as possible), drop it somewhere and it runs whatever the machine, given a basic set of environmental requirements. In J2EE world, when you deploy an application in an app server you put your own JAR’s in the application’s own class-path – you wouldn’t put them in the app-server’s global classpath. So (in my mind) it should be in .NET and libraries shouldn’t be in the GAC unless they are part of, or an extension of, the .NET runtime itself.

I especially don’t like that I can build something referencing a non-Runtime library in the GAC and not be given a warning.

The oft-quoted reason for using the GAC is that ‘it saves you having multiple copies of dll’s all over the place’. My response to this is that premature optimization is the root of all evil and that disk space is cheap, and the pain that shared libraries can give you does not merit the storage space / download bandwidth gain.

So in conclusion, the GAC is better than the dll-hell of COM (which thankfully I avoided by living in Java world for a few years), but still isn’t as good as not sharing library files across applications at all. My advice is don’t use the GAC unless you absolutely have to, or all the applications you use explicitally specify which versions of libraries they require.