Lessons · Fundamental Applications

What is a private constructor?

A constructor is the piece of code that runs when an object is born. Writing new Commitment(...) means: allocate a fresh object, then run its constructor to fill it in. Every class has at least one, even if the compiler writes it for you.

private is a visibility rule. A private member can be used only by code inside the same class. So a private constructor is a birth ritual that only the class itself may perform: no outside code can write new Commitment(...) — the compiler refuses.

Why would a class hide its own constructor?

To control its doors. If the constructor were public, every corner of the codebase could create commitments any way it liked, and every rule about what a valid commitment is would have to be enforced everywhere. Making the constructor private and offering one named method instead concentrates creation in a single place the class controls:

public static Commitment Create(
    Guid ownerId,
    string title,
    DateTimeOffset startsAt,
    DateTimeOffset endsAt,
    string timeZone,
    DateTimeOffset createdAt)
{
    return new Commitment(
        Guid.NewGuid(),
        ownerId,
        title,
        startsAt,
        endsAt,
        timeZone,
        createdAt);
}

Create lives inside the class, so it is allowed to call the private constructor. Everyone else must go through Create — which means everyone gets the same validation, the same trimming, the same freshly minted identity. There is exactly one door into existence, and the class owns it.

The two private constructors in Commitment

The entity in the walkthrough has two. The full one takes seven parameters and runs Validate before assigning anything, so an invalid commitment can never be half-built. The empty one takes no parameters at all:

private Commitment()
{
}

That one exists for a single caller: Entity Framework. When EF reads a saved row back from the database, it constructs the object without arguments and then writes each column value into the matching property. It is allowed to do this despite the private keyword because it uses reflection — a controlled exception the class tolerates for rehydration, since the row already passed validation when it was first saved.

What to remember

A private constructor does not mean "this class cannot be created." It means "this class decides how it is created." Seeing one should make you look for the named factory method nearby — that method is the real public story of how the object comes to exist.

Seen in: Walkthrough 01 — Create rejects an inverted interval, step 11, entering the private constructor of Commitment in src/CalendarSystem.Domain/Commitments/Commitment.cs.