Static Factory Methods vs Constructors In C#

Recently while pair programming with a colleague, we got into discussing the best way to initialize new objects in C#. I’ve always just implemented constructors and left it at that, while he tended to favour static factory methods. This led to a lot of discussion and back-and-forth about the pros and cons of each type.

Just to clarify what I’m talking about, here’s an example of both

// Using the constructor
SqlConnection myConnection = new SqlConnection(connectionString);

// Using a static factory method
IDbConnection myConnection = SqlConnection.FromConnectionString(connectionString);

I’ve never considered implementing these static factory methods before and I naturally scorned what I didn’t understand. I’ve since changed my mind — let’s dive into the pros & cons.

Pros of Static Factory Methods

No need to return a new instance

You can’t use a cached object or return null if the object creation fails. I think for most application code, you probably don't need to do this, but the ability is certainly nice. Particularly if you're writing library code, you might appreciate the flexibility in the future.

You can use method references

// Static factory method - the method group can be passed in directly as a function reference
var bars = myFoo
.Select(bar.FromFoo)

// Constructors - you have to pass in a lambda that constructs the instance via new.
var bars = myFoo
.Select(f => new Bar(f));

There’s no functional difference in this code — it’s only a matter of taste in code style, so it probably shouldn’t weight too heavily into the decision.

You can name ‘em

// With constructors
var color = new Color(25, 25, 5, 80);
var color = new Color(100, 150, 50);

// With static factory methods
var color = Color.FromCMYK(25, 25, 5, 80);
var color = Color.FromRGB(100, 150, 50);

Unless you know that the four value constructor of Color is CMYK and the three value constructor is RGB, it’s impossible to tell by reading the code. Contrast that with the static factory methods which are much more descriptive.

I think if you have different ways to construct an object, particularly ones where the parameters resemble each other, there’s a strong case for using the static factory methods.

Factory Methods can return a different class

// This could create an IpV4IpAddress that implements IIpAddress 
IIpAddress ipv4Address = IpAddress.FromString("127.0.0.1");

// This could create an IpV6IpAddress that implements IIpAddress
IIpAddress ipv6Address = IpAddress.FromString("2001:0db8:0a0b:12f0:0000:0000:0000:0001")

Being able to return a different actual type depending on the input is probably pretty valuable when providing public APIs, such as in library contexts. Particularly because it means you can hide some implementation details behind an interface or a base class.

I’m not sure the value is as great in application code, where you control the whole codebase and can make large-scale refactorings much easier.

There Are Things You Shouldn’t Do In Constructors

Some people also don’t think you should throw exceptions in constructors. Perhaps it depends on the language, but in C# it’s totally fine, with some caveats if you’re creating umanaged resources in your constructor.

Cons of Static Factory Methods

There Are Things You Shouldn’t Do In Constructors

There’s more code

They’re harder to find

I think my biggest issue I have with the static factory methods is the discoverability you lose.

After doing the research and thinking about it, I think my opinion is this currently:

  • You should always create one constructor that maps 1:1 to the fields internally in the class.
  • If you need to do anything fancy to create the object, such as IO, or you’re interested in caching objects and reusing them, use a static factory method.
  • If you need API stability, such as for library development, hide that constructor and use a static factory method because of the implementation flexibility it gives you.
  • If you have multiple different ways to create your class, create static factory methods and use those, because of the descriptiveness they give you.

Did you enjoy this post? Please share it!

Originally published at https://www.gustavwengel.dk.