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
readonlyinitialization 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
readonlyfields. - It makes classes easier to maintain.
- It reduces bugs caused by forgetting to update all constructors.
A readonly field can be assigned:
Mental Model
Think of constructors like different entrances to the same building.
- One entrance accepts an
intdirectly. - Another entrance accepts a
string, but first converts it into anint.
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 setupSample(string)= a convenience entrance that prepares the value and forwards it
This way, all important setup happens in one place.
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.
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
new Sample("42")is called.- C# selects the constructor that accepts a
string. - Before that constructor body runs, the
: this(int.Parse(theIntAsString))part executes. int.Parse("42")returns42.
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( baseUrl) : ()
{
}
}
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)
{
(.IsNullOrWhiteSpace(name))
ArgumentException(, (name));
_name = name;
}
{
}
}
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(.Parse(theIntAsString));
}
Comparisons
| Concept | What it does | Best use case |
|---|---|---|
this(...) | Calls another constructor in the same class | Reusing initialization logic across overloads |
base(...) | Calls a constructor in the parent class | Initializing inherited state |
| Helper method | Moves repeated logic into a normal method | Shared behavior that does not depend on constructor-only assignment |
| Field initializer | Assigns a field where it is declared | Simple default values |
this(...) vs helper method
| Feature | this(...) | Helper method |
|---|
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
readonlyfields.
Example
public class Sample
{
private readonly int _intField;
public Sample(int theInt)
{
_intField = theInt;
}
public Sample(string text) : this(int.Parse(text))
{
}
}
Common pitfalls
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(...).
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
Temperatureclass with a privatereadonlyfield for Celsius. - Add one constructor that accepts a
double. - Add one constructor that accepts a
stringand converts it to adouble. - 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.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
C# Type Checking Explained: typeof vs GetType() vs is
Learn when to use typeof, GetType(), and is in C#. Understand exact type checks, inheritance, and safe type testing clearly.
C# Version Numbers Explained: C# vs .NET Framework and Why “C# 3.5” Is Incorrect
Learn the correct C# version numbers, how they map to .NET releases, and why terms like C# 3.5 are inaccurate and confusing.