When it comes to API design, static classes are a bit of a bugbear. Quite often there are arguments both for and against exposing a given function as a static function as opposed to an instance method.

The primary argument for static functions is simplicity. You can use them anywhere in the code without worry about creating and managing instances, dependency injection, etc. And since you aren’t creating new instances that have to be garbage collected, performance should be better as well.

That is, unless you are managing state. Then all of your static functions need to be made thread-safe, which involves potentially expensive locking and/or synchronization techniques. And even if individual calls are thread-safe, you may find the need to treat a series of calls as one atomic transaction. This is where AutoMapper enters the story.

While originally based around the use of static functions, over time AutoMapper became more and more configurable. And with each new configuration option, more state had to be managed and more potential threading issues arose. So back in January, Jimmy Bogard marked the static functions in AutoMapper 4.2 as obsolete with the intention of eventually removing them.

As I work towards the 4.2 release of AutoMapper, I got a little inspiration. Over the past year or so I’ve given some talks/podcasts about a long-lived open source codebase. One of my biggest regrets was that I made AutoMapper have a static API from literally the very beginning. The first tests/prototypes of AutoMapper all started out with “Mapper.CreateMap” and “Mapper.Map”. I showed my boss, Jeffrey Palermo, at the time and asked what he thought, and he said “looks great Jimmy, maybe you shouldn’t make it static” and I said “PFFFFFFFFFFFT NO WAY”. Well, I’ve seen the problems with static and I’ve regretted it ever since. With the upcoming release, I’ve had a chance to prototype what it might look like without static – it worked great – and I’m ready to mark the entire static API as obsolete.

This change does pose some problems. One of the features of AutoMapper is its support for a fluent API that works with LINQ expression chains. This feature requires the use of extension methods, which are always defined as static functions.

The work around is to continue offering LINQ support, but in a way that doesn’t require the use of global state. Instead, you pass in the AutoMapper configuration info to the LINQ expression. It is a bit more verbose, but in some ways more flexible.

Here is an example from the Migrating from static API guide.

public class ProductsController : Controller { public ProductsController(MapperConfiguration config) { this.config = config; } private MapperConfiguration config; public ActionResult Index(int id) { var dto = dbContext.Products .Where(p => p.Id == id) .ProjectTo (config) .SingleOrDefault(); return View(dto); } }

A month later, Jimmy Bogard decided to restore the static functions. He writes,

The big pain from the static API was that the configuration could be changed at any time, and I couldn’t enforce a clear configuration step. Thinking about it, there was really nothing wrong with having a static API but just forcing you to initialize before mapping. That’s what will be allowed going forward – the instance API is now completely flushed out, and the static API is truly a thin veneer on top of it, where you call a static Initialize method instead of a constructor. This release removes some of the obsolete attributes and restores the LINQ projections that use the static configuration.

InfoQ asks, what is your stance on the use of stateful static functions versus only allowing instance methods?