Menu

C# Constructor: Default, Parameterized, this() and base() Chaining

How C# constructors work: the implicit default constructor and when it disappears, parameterized and overloaded constructors, chaining with this(...) and base(...), the order things run in, static and private constructors, and C# 12 primary constructors.

This page includes runnable editors - edit, run, and see output instantly.

A constructor is the code that runs when you create an object with new. It has the same name as the class, no return type, and its job is to put the new object into a valid state before anyone uses it.

Output:

Mug: 8.50
Rejected: price

Because the constructor refuses a negative price, no Product with a negative price can exist. That guarantee is the main reason to write constructors instead of setting fields from outside.

The default constructor, and when it disappears

If a class declares no constructor, the compiler supplies a public parameterless one that does nothing beyond running field initializers. That is why new BankAccount() works on a class with only fields.

The moment you declare any constructor, that implicit one is no longer generated:

class Product
{
    public string Name;
    public Product(string name) { Name = name; }
}

var p = new Product();   // error CS7036: There is no argument given that corresponds to the required parameter 'name'

This surprises people when a serializer, an ORM or a generic new() constraint needs a parameterless constructor. If you want both, declare the parameterless one yourself:

public Product() { }                       // or
public Product() : this("Unnamed") { }     // delegate to the other one (next section)

A constructor may be public, internal, protected or private. Its access decides who may create objects with it.

Overloading and chaining with this(...)

A class can have several constructors with different parameter lists. To avoid copying the same assignments into each one, chain them: : this(...) calls another constructor of the same class before the current body runs.

Output:

new Pizza():
  full constructor: medium, classic, 0
  size-only constructor body
  parameterless constructor body
Result: medium classic with 0 toppings

The chain runs the most complete constructor first and unwinds back to the one you called. Keep the real work (validation, assignments) in one constructor and let the others only supply defaults.

Optional parameters are an alternative: public Pizza(string size = "medium", string crust = "classic", int toppings = 0) gives one constructor that covers all three calls. Chaining is still the better fit when the shorter constructors need to compute something, or when changing a default must not require callers to recompile (optional parameter defaults are copied into the calling code at compile time).

Calling a base class constructor with base(...)

A derived class does not inherit constructors. Every constructor of the derived class must run a constructor of the base class first. If you write nothing, the compiler inserts a call to the base's parameterless constructor; if the base has none, you must pick one with : base(...).

The order everything runs in is worth seeing once:

Output:

Truck field initializer
Vehicle field initializer
Vehicle constructor body
Truck constructor body
KL-204, 3 axles

Field initializers run first, derived class before base class, and then the constructor bodies run from the base down. So by the time Truck's body runs, Plate is already set. The one trap in this order: if the base constructor calls a virtual method that Truck overrides, the override runs before Truck's constructor body, and sees Axles still at 0. Avoid calling virtual methods from constructors.

Static constructors

A static constructor initializes the type rather than an object. It has no parameters and no access modifier, and the runtime calls it exactly once, just before the type is first used.

Output:

Program started
Loading tax table (runs once)
123.00
119.00

The runtime makes the static constructor thread-safe: even if several threads touch the type at once, it runs one time. If it throws, every later use of the type throws TypeInitializationException for the life of the process, so keep it simple and free of I/O that can fail.

Constructor vs object initializer

An object initializer, new Pizza("large") { Toppings = 3 }, is not a second constructor. The compiler turns it into "run the constructor, then assign these members". Use each for what it is good at:

  • Constructor parameters for values the object cannot be valid without. Every caller must pass them, and the constructor can check them.
  • Initializer for optional settings with sensible defaults.
var order = new Order(customerId: 42) { Note = "Leave at the door", GiftWrap = true };

Since C# 11, a property marked required must be set in the initializer, which gives initializer syntax some of the constructor's guarantees. That is covered on the properties page.

Private constructors

A private constructor means only the class itself can create instances. Two patterns use it. A static factory method, where the class controls creation and can return a cached object or null, and a singleton:

Output:

21
100

The compiler error for new Temperature(5m) outside the class is CS0122, the same one access modifiers produce for any private member. Named factory methods solve a real limitation: two constructors cannot both take one decimal, but FromCelsius and FromFahrenheit can. A class with only static members (a utility class) should be declared static instead of hiding its constructor.

Expression-bodied constructors

A constructor whose body is one statement can use =>:

public Product(string name) => Name = name;

With tuples you can even assign several fields in one line: public Point(int x, int y) => (X, Y) = (x, y);.

Primary constructors (C# 12)

C# 12 lets a class or struct declare its constructor parameters on the type itself. The parameters are in scope in every member:

public class Customer(string name, int id)
{
    public string Name { get; } = name;          // copy into a property
    public string Label => $"#{id} {Name}";      // or read a parameter directly

    public Customer(string name) : this(name, 0) { }   // other constructors must chain to it
}

Two differences from records surprise people. A class's primary constructor parameters do not become public properties; you expose them yourself. And a parameter used inside a member is captured into a hidden field that stays mutable, so name = "x"; inside a method compiles. Primary constructors are most at home for dependency injection, where the parameters are services the class only calls:

public class OrderService(IOrderRepository repo, ILogger<OrderService> log)
{
    public Order Get(int id) => repo.Find(id);
}

Common mistakes

  • Losing the parameterless constructor. Adding a parameterized constructor removes the implicit one (CS7036 at every new X()).
  • Forgetting : base(...) when the base class has no parameterless constructor. The compiler cannot insert the implicit call and reports that there is no argument for the base constructor's required parameter.
  • Calling virtual methods in a constructor. The override runs before the derived constructor's body.
  • Heavy work in a constructor. Network calls, file reads or anything slow make objects expensive and exceptions hard to handle. Use a static factory method, or an async initialization method, for that work.
  • Writing a return type. public void Product() is an ordinary method named Product, and the compiler rejects it because a member cannot have the same name as its enclosing type (CS0542).

Frequently Asked Questions

What is a constructor in C#?

A constructor is a special method that runs when an object is created with new. It has the same name as the class and no return type: public Product(string name) { Name = name; }. Its job is to leave the new object in a valid state, typically by assigning fields from its parameters and rejecting bad input.

Does C# create a default constructor automatically?

Only when the class declares no constructor at all. Then the compiler adds a public parameterless one that leaves every field at its initializer or default value. As soon as you write any constructor, for example one that takes a name, the implicit one is gone and new Product() stops compiling (error CS7036). Declare public Product() { } yourself if you still need it.

How do I call one constructor from another in C#?

Use : this(...) after the constructor's parameter list: public Product(string name) : this(name, 0m) { }. The target constructor runs first, then the body of the one you called. To call a constructor of the base class, use : base(...) the same way.

What is a static constructor in C#?

A constructor marked static, with no parameters and no access modifier, that runs once per type before the first instance is created or the first static member is used. It is used to initialize static fields that need more than a one-line initializer. You cannot call it yourself, and if it throws, the type becomes unusable for the rest of the program (TypeInitializationException).

Should I use a constructor or an object initializer?

Use constructor parameters for values the object cannot be valid without, because the compiler forces every caller to pass them and the constructor can check them. Use an object initializer (new Product("Mug") { Color = "blue" }) for optional settings. The initializer runs after the constructor finishes.

What are primary constructors in C# 12?

Parameters written on the class declaration itself, class Customer(string name, int id) { ... }, available to every member of the class. Unlike a record's positional parameters, they do not become public properties: expose them explicitly with public string Name => name; or public string Name { get; } = name;.

Coddy programming languages illustration

Learn to code with Coddy

GET STARTED