Question

How to Call One Constructor from Another in C#

csharpconstructor

Question

You have a C# class with two constructors that both initialize readonly fields.

One constructor receives the final value directly, while the other performs some conversion first and then assigns the result. You want to avoid duplicating the field assignment logic.

For example:

public class Sample
{
    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);
        _intField = i;
    }

    public Sample(int theInt) => _intField = theInt;

    public int IntProperty => _intField;

    private readonly int _intField;
}

The problem is:

  • You do not want to duplicate the assignment code.
  • The field is readonly, so it must be assigned during construction.
  • Moving the shared logic to a normal helper method does not solve the readonly initialization requirement.
  • You want to know how to call one constructor from another in C#.

How can this be done cleanly and correctly?

Short Answer

By the end of this page, you will understand constructor chaining in C#, how to use this(...) to call one constructor from another, and why this is especially useful when initializing readonly fields without duplicating code.

Concept

In C#, a class can have multiple constructors. This is called constructor overloading. Often, several constructors perform similar setup work, which can lead to duplicated code.

To avoid that duplication, C# supports constructor chaining. This means one constructor can call another constructor in the same class by using this(...).

For your example, one constructor already knows how to fully initialize the object:

public Sample(int theInt) => _intField = theInt;

The string-based constructor does not need to assign the field itself. It can first convert the string to an int, then pass that value to the other constructor:

public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
{
}

This matters because:

  • It keeps initialization logic in one place.
  • It works correctly with readonly fields.
  • It makes classes easier to maintain.
  • It reduces bugs caused by forgetting to update all constructors.

A readonly field can be assigned:

  • where it is declared, or
  • inside a constructor

Constructor chaining still counts as constructor-time initialization, so it is the standard solution here.

Mental Model

Think of constructors like different entrances to the same building.

  • One entrance accepts an int directly.
  • Another entrance accepts a string, but first converts it into an int.

Instead of building two separate check-in desks, you create one main check-in desk. The string entrance simply forwards visitors to the int entrance after converting the value.

So:

  • Sample(int) = the main entrance that performs the real setup
  • Sample(string) = a convenience entrance that prepares the value and forwards it

This way, all important setup happens in one place.

Take Quiz

Syntax and Examples

Core Syntax

To call another constructor in the same class, use : this(...) after the constructor signature.

public ClassName(argumentType value) : this(otherValue)
{
}

Your Example Using Constructor Chaining

public class Sample
{
    private readonly int _intField;

    public Sample(int theInt)
    {
        _intField = theInt;
    }

    public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
    {
    }

    public int IntProperty => _intField;
}

What this does

  • Sample(int) performs the actual field assignment.
  • Sample(string) parses the string and forwards the result.
  • _intField is assigned only once.

Another Example

public class User
{
    private readonly string _name;
    private readonly int _age;

    public User(string name, int age)
    {
        _name = name;
        _age = age;
    }

    public User(string name) : this(name, 18)
    {
    }

    public string Name => _name;
    public int Age => _age;
}

Explanation

Here, the one-argument constructor supplies a default age and delegates to the main constructor.

Using Expression-Bodied Constructors

Your original code used one. You can still combine styles if you want:

public class Sample
{
    private readonly int _intField;

    public Sample(int theInt) => _intField = theInt;

    public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
    {
    }

    public int IntProperty => _intField;
}

That is valid C# and keeps the code concise.

Step by Step Execution

Consider this code:

var sample = new Sample("42");
Console.WriteLine(sample.IntProperty);

With this class:

public class Sample
{
    private readonly int _intField;

    public Sample(int theInt)
    {
        _intField = theInt;
    }

    public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
    {
    }

    public int IntProperty => _intField;
}

Step by step

  1. new Sample("42") is called.
  2. C# selects the constructor that accepts a string.
  3. Before that constructor body runs, the : this(int.Parse(theIntAsString)) part executes.
  4. int.Parse("42") returns 42.
  5. C# calls Sample(int) with 42.
  6. Inside Sample(int), _intField is assigned 42.
  7. Control returns to the Sample(string) constructor body.
  8. Its body is empty, so construction finishes.
  9. sample.IntProperty returns 42.

Important detail

The chained constructor call happens before the constructor body executes. That is why constructor chaining is part of the constructor declaration, not a normal method call inside the body.

Real World Use Cases

Constructor chaining is common whenever a class can be created in multiple ways but should still follow one central initialization path.

Common scenarios

  • Parsing input
    • Create an object from a string, but store the parsed numeric or date value.
  • Default values
    • A shorter constructor fills in default configuration values.
  • Convenience overloads
    • Let callers pass fewer arguments while routing to a fuller constructor.
  • Validation
    • Convert or validate input first, then delegate to the main constructor.
  • Configuration objects
    • Support both simple and advanced object creation patterns.

Example: API client configuration

public class ApiClient
{
    private readonly string _baseUrl;
    private readonly int _timeoutSeconds;

    public ApiClient(string baseUrl, int timeoutSeconds)
    {
        _baseUrl = baseUrl;
        _timeoutSeconds = timeoutSeconds;
    }

    public ApiClient(string baseUrl) : this(baseUrl, 30)
    {
    }
}

This lets callers create an API client with a default timeout or specify one explicitly.

Take Quiz

Real Codebase Usage

In real projects, developers usually pick one primary constructor overload that does the actual assignment and validation, then make other constructors delegate to it.

Common patterns

1. Convenience overloads

public ReportGenerator(string outputPath) : this(outputPath, false)
{
}

This avoids repeating assignments.

2. Input normalization before delegation

public Product(string priceText) : this(decimal.Parse(priceText))
{
}

The string-based constructor converts data into the real internal type.

3. Guard clauses in the main constructor

public class Person
{
    private readonly string _name;

    public Person(string name)
    {
        if (string.IsNullOrWhiteSpace(name))
            throw new ArgumentException("Name is required.", nameof(name));

        _name = name;
    }

    public Person() : this("Unknown")
    {
    }
}

The validation lives in one place.

4. Reducing maintenance cost

If a class later gains another readonly field, you only update the main constructor instead of every overload.

Why teams prefer this

  • Less duplicated logic
  • More consistent validation
  • Easier refactoring
  • Better readability once you know the pattern

Common Mistakes

1. Duplicating initialization logic

Problem

public class Sample
{
    private readonly int _intField;

    public Sample(int theInt)
    {
        _intField = theInt;
    }

    public Sample(string theIntAsString)
    {
        int i = int.Parse(theIntAsString);
        _intField = i;
    }
}

This works, but the assignment logic is repeated.

Better

public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
{
}

2. Trying to call another constructor like a method

Broken code

public Sample(string theIntAsString)
{
    Sample(int.Parse(theIntAsString));
}

Constructors are not normal methods. You cannot call them inside the body like this.

Fix

Use : this(...) in the constructor declaration.

3. Using a helper method to assign a readonly field later

Broken idea

private void Init(int value)
{
    _intField = value;
}

This may fail because readonly fields must be assigned during declaration or construction, not from arbitrary methods.

Fix

Put the assignment in one constructor and chain to it.

4. Forgetting parse errors

Risk

public Sample(string theIntAsString) : this(int.Parse(theIntAsString))
{
}

If the string is not a valid integer, int.Parse throws an exception.

Safer alternative

public Sample(string theIntAsString) : this(ParseOrThrow(theIntAsString))
{
}

private static int ParseOrThrow(string value)
{
    if (!int.TryParse(value, out int result))
        throw new ArgumentException("Value must be a valid integer.", nameof(value));

    return result;
}

5. Creating constructor cycles

Broken code

public Sample(int x) : this(x.ToString())
{
}

public Sample(string s) : this(int.Parse(s))
{
}

These constructors call each other forever, which is not allowed.

Fix

Choose one constructor as the main one and have the others delegate to it.

Comparisons

ConceptWhat it doesBest use case
this(...)Calls another constructor in the same classReusing initialization logic across overloads
base(...)Calls a constructor in the parent classInitializing inherited state
Helper methodMoves repeated logic into a normal methodShared behavior that does not depend on constructor-only assignment
Field initializerAssigns a field where it is declaredSimple default values

this(...) vs helper method

Featurethis(...)Helper method
Works naturally with readonly fieldsYesOften not suitable for assignment
Avoids duplicated constructor logicYesSometimes
Runs during object constructionYesNot always in the right way
Good for overload delegationYesNo

this(...) vs base(...)

  • Use this(...) when calling another constructor in the same class.
  • Use base(...) when calling a constructor from the parent class.

Example:

public class Animal
{
    public Animal(string name) { }
}

public class Dog : Animal
{
    public Dog() : base("Dog")
    {
    }
}
Take Quiz

Cheat Sheet

Quick syntax

public MyClass(string text) : this(int.Parse(text))
{
}

Rules

  • Use : this(...) to call another constructor in the same class.
  • The chained constructor call appears in the constructor declaration, not in the body.
  • One constructor should usually be the main constructor.
  • Other constructors should prepare values and delegate to it.
  • This is a good pattern for initializing readonly fields.

Example

public class Sample
{
    private readonly int _intField;

    public Sample(int theInt)
    {
        _intField = theInt;
    }

    public Sample(string text) : this(int.Parse(text))
    {
    }
}

Common pitfalls

  • Do not try to call a constructor like a normal method.
  • Do not create circular constructor chains.
  • Be careful with parsing methods that can throw exceptions.
  • Keep validation in one main constructor when possible.

Related syntax

  • this(...) = same class constructor
  • base(...) = parent class constructor

FAQ

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

Use : this(...) after the constructor signature.

public Sample(string text) : this(int.Parse(text))
{
}

Can readonly fields be assigned through constructor chaining?

Yes. If the field is assigned in the constructor that gets called through this(...), it is still considered valid constructor-time initialization.

Should every constructor assign fields directly?

Not usually. A common pattern is to have one main constructor do the assignments, while other constructors delegate to it.

What is the difference between this(...) and base(...) in C#?

  • this(...) calls another constructor in the same class.
  • base(...) calls a constructor in the parent class.

Can I call a constructor from inside another constructor body?

No. In C#, constructor chaining must be declared with : this(...) or : base(...).

What happens if int.Parse fails in a chained constructor?

It throws an exception before object construction completes. If the input may be invalid, consider using int.TryParse with explicit error handling.

Is constructor chaining good practice?

Yes, when multiple constructors share initialization logic. It reduces duplication and keeps object creation consistent.

Take Quiz

Mini Project

Description

Build a small Temperature class that can be created either from a numeric Celsius value or from a string such as "25". This demonstrates constructor chaining, avoids duplicated initialization logic, and shows how to keep readonly field assignment in one place.

Goal

Create a class with multiple constructors where one constructor parses input and delegates to the main constructor.

Requirements

  • Create a Temperature class with a private readonly field for Celsius.
  • Add one constructor that accepts a double.
  • Add one constructor that accepts a string and converts it to a double.
  • Use constructor chaining so the field is assigned in only one constructor.
  • Expose the stored value through a read-only property.
  • Print results from both constructors in a small demo program.
Take Quiz

Keep learning

Related questions

View more