Question
If a class inherits from a base class in C# and you want to pass values from the derived class constructor to the base class constructor, how do you do that?
For example, suppose you inherit from Exception and want to pass the message value to the base Exception constructor:
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo)
{
// How do you pass message to the base Exception constructor?
base(message);
}
}
The goal is to pass the message string to the base Exception class constructor correctly.
Short Answer
By the end of this page, you will understand how constructor chaining works in C#, how to call a base class constructor using : base(...), and why this is especially useful when creating custom exception classes and other derived types.
Concept
In C#, when you create an object from a derived class, the base part of that object must be initialized too. That means the base class constructor runs as part of object creation.
If the base class needs arguments, you must pass them in the constructor declaration, not from inside the constructor body. C# uses constructor initializer syntax for this:
public Child(string value) : base(value)
{
}
This matters because the base class must be constructed before the derived class constructor body runs. By the time execution enters the { ... } body of your derived constructor, base initialization has already happened.
For your Exception example, the correct approach is:
class MyExceptionClass : Exception
{
public string ExtraInfo { get; }
public MyExceptionClass(string message, string extraInfo) : base(message)
{
ExtraInfo = extraInfo;
}
}
This passes message to Exception, while the derived class handles its own additional data.
Why this matters in real programming:
- Many framework classes require constructor parameters.
- You often extend base types while preserving their built-in behavior.
- Custom exceptions, controllers, models, and service classes commonly use constructor chaining.
- It keeps object initialization correct and predictable.
Mental Model
Think of building a house extension.
- The base class is the original house.
- The derived class is the new extension.
- Before you can finish the extension, the original house must already exist.
So in C#, the base constructor is called first to build the base part of the object. Then the derived constructor finishes the rest.
base(...) is like saying: "First, build the original part using these materials, then I will add my own part."
Syntax and Examples
Core syntax
Use : base(...) after the constructor signature:
public DerivedType(arg1, arg2) : base(baseArg1, baseArg2)
{
// derived class setup
}
Basic example
using System;
class Person
{
public string Name { get; }
public Person(string name)
{
Name = name;
}
}
class Employee : Person
{
public int EmployeeId { get; }
public Employee(string name, int employeeId) : base(name)
{
EmployeeId = employeeId;
}
}
Explanation
Personrequires aname.Employeeinherits fromPerson.Employeepassesnameto the base constructor using: base(name).- Then it initializes its own property,
EmployeeId.
Custom exception example
using System;
class MyExceptionClass : Exception
{
public string ExtraInfo { get; }
public MyExceptionClass(string message, string extraInfo) : base(message)
{
ExtraInfo = extraInfo;
}
}
Why this works
Exceptionalready knows how to store the message.- Your custom exception adds
ExtraInfo. : base(message)ensures the standard exception message behavior still works.
Passing multiple values to the base constructor
class Animal
{
public string Name { get; }
public int Age { get; }
public Animal(string name, int age)
{
Name = name;
Age = age;
}
}
class Dog : Animal
{
public string Breed { get; }
public Dog(string name, int age, string breed) : base(name, age)
{
Breed = breed;
}
}
Step by Step Execution
Consider this example:
using System;
class Person
{
public string Name { get; }
public Person(string name)
{
Console.WriteLine("Person constructor running");
Name = name;
}
}
class Employee : Person
{
public int Id { get; }
public Employee(string name, int id) : base(name)
{
Console.WriteLine("Employee constructor running");
Id = id;
}
}
var employee = new Employee("Ava", 42);
Console.WriteLine(employee.Name);
Console.WriteLine(employee.Id);
What happens step by step
new Employee("Ava", 42)starts creating anEmployeeobject.- C# sees
: base(name)in theEmployeeconstructor. - It calls
Person("Ava")first. - Inside
Person,Nameis set to"Ava". - The
Personconstructor finishes. - Control returns to the
Employeeconstructor body. Idis set to42.- The
Employeeobject is fully created.
Output
Person constructor running
Employee constructor running
Ava
42
The important rule is:
- Base constructor first
- Derived constructor body second
That is why base(message); cannot appear as a normal statement inside the constructor body.
Real World Use Cases
Using base constructors appears in many practical C# scenarios:
Custom exceptions
class ValidationException : Exception
{
public ValidationException(string message) : base(message)
{
}
}
Used when you want standard exception behavior plus your own exception type.
Reusing common initialization
class DbEntity
{
public Guid Id { get; }
public DbEntity(Guid id)
{
Id = id;
}
}
class User : DbEntity
{
public string Email { get; }
public User(Guid id, string email) : base(id)
{
Email = email;
}
}
Useful when multiple classes share common fields.
UI or framework classes
Some framework base classes need configuration values during construction. Derived classes pass those values upward.
API models and domain objects
A base class may enforce required state such as IDs, names, timestamps, or metadata. Derived classes add specialized data while still calling the base constructor.
Real Codebase Usage
In real projects, developers commonly use base constructor calls in these patterns:
Passing required state upward
If the base class owns a piece of data, let the base class initialize it.
class AppError : Exception
{
public AppError(string message) : base(message) { }
}
Keeping derived constructors small
Avoid repeating base setup logic in every child class.
class Entity
{
public DateTime CreatedAt { get; }
public Entity()
{
CreatedAt = DateTime.UtcNow;
}
}
class Order : Entity
{
public decimal Total { get; }
public Order(decimal total) : base()
{
Total = total;
}
}
Validation before storing local values
You can still validate arguments in the derived constructor body, but constructor chaining happens before the body runs. If the validation affects values passed to the base constructor, do it in the argument expression.
class ProductBase
{
public string Name { get; }
public ProductBase(string name)
{
Name = name;
}
}
class Product : ProductBase
{
public Product(string name) : base(string.IsNullOrWhiteSpace(name) ? "Unknown" : name)
{
}
}
Exception class conventions
Custom exceptions often provide multiple constructors:
using System;
class MyExceptionClass : Exception
{
public MyExceptionClass() { }
public MyExceptionClass(string message) : base(message) { }
public MyExceptionClass(string message, Exception innerException)
: base(message, innerException) { }
}
This matches common .NET exception patterns.
Common Mistakes
1. Trying to call base(...) inside the constructor body
This is the mistake from the original question.
Incorrect
class MyExceptionClass : Exception
{
public MyExceptionClass(string message)
{
base(message); // Invalid
}
}
Correct
class MyExceptionClass : Exception
{
public MyExceptionClass(string message) : base(message)
{
}
}
2. Forgetting that the base constructor runs first
Beginners sometimes expect derived fields to be available before base(...) runs.
class Base
{
public Base(string value) { }
}
class Child : Base
{
private string _text;
public Child(string text) : base(_text) // Problem: instance field not ready here
{
_text = text;
}
}
Use constructor parameters or static/helper expressions instead.
3. Not calling a required base constructor
If the base class has no parameterless constructor, you must supply the required arguments.
class Parent
{
public Parent(string name) { }
}
class Child : Parent
{
public Child() // Error: no base constructor specified
{
}
}
Fix:
class Child : Parent
{
public Child(string name) : base(name)
{
}
}
4. Duplicating data unnecessarily
If Exception already stores the message, you usually do not need your own separate MessageText field.
5. Creating incomplete custom exceptions
For production code, custom exceptions often include standard constructors such as message-only and message-plus-inner-exception constructors.
Comparisons
| Concept | Purpose | Syntax | When to use |
|---|---|---|---|
base(...) | Calls a base class constructor | public Child() : base(...) | When the parent class must be initialized |
this(...) | Calls another constructor in the same class | public Child() : this(...) | When you want to reuse constructor logic within the same class |
base.Member | Accesses a base class method or property | base.ToString() | When you want the parent implementation |
| constructor body | Runs derived class logic after base initialization | { ... } | For setting up the child class |
base(...) vs this(...)
class Example
{
public Example() : this("default")
{
}
public Example(string name)
{
}
}
this(...)stays in the same class.base(...)goes to the parent class.
base(...) vs base.Member
class Parent
{
public virtual void Print() => Console.WriteLine("Parent");
}
class Child : Parent
{
public override void Print()
{
base.Print();
Console.WriteLine("Child");
}
}
base.Print()calls a base method.: base(...)calls a base constructor.
Cheat Sheet
class Child : Parent
{
public Child(string value) : base(value)
{
}
}
Rules
- Use
: base(...)after the constructor signature. - The base constructor runs before the derived constructor body.
- You cannot call
base(...)like a normal method inside{}. - If the base class has no parameterless constructor, you must call one of its existing constructors.
- Use
this(...)to call another constructor in the same class.
Exception example
class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extraInfo) : base(message)
{
ExtraInfo = extraInfo;
}
public string ExtraInfo { get; }
}
Common pattern for custom exceptions
class MyExceptionClass : Exception
{
public MyExceptionClass() { }
public MyExceptionClass(string message) : base(message) { }
public MyExceptionClass(string message, Exception innerException)
: base(message, innerException) { }
}
Edge case
This is invalid:
public Child(string name)
{
base(name); // invalid
}
FAQ
How do you call a base constructor in C#?
Use : base(arguments) after the derived constructor declaration.
public Child(string name) : base(name)
{
}
Can I call base() inside the constructor body?
No. Base constructors must be called using constructor initializer syntax, not as a statement inside the body.
What happens if I do not call a base constructor explicitly?
C# tries to call the parameterless base constructor automatically. If the base class does not have one, you get a compile-time error.
How do I pass a message to Exception from a custom exception?
Use:
public MyExceptionClass(string message) : base(message)
{
}
What is the difference between base(...) and this(...)?
base(...)calls a constructor in the parent class.this(...)calls another constructor in the same class.
Should custom exceptions have multiple constructors?
Usually yes, especially in .NET codebases. Common constructors include parameterless, message-only, and message-plus-inner-exception.
Does the base constructor always run first?
Yes. The base constructor finishes before the derived constructor body runs.
Mini Project
Description
Create a small C# example with a base class and a derived class that passes data to the base constructor. This project helps you practice constructor chaining in a realistic way by modeling an application-specific exception with extra context.
Goal
Build a custom exception class that passes its message to Exception and stores additional information in its own property.
Requirements
- Create a class that inherits from
Exception. - Add a constructor that accepts
messageand one extra value such asextraInfo. - Pass
messageto the baseExceptionconstructor using: base(message). - Store the extra value in a public read-only property.
- Throw the exception and print both the standard message and the extra information.
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.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Access Modifiers and static: public, private, protected, and Defaults
Learn how C# public, private, protected, and default access control visibility, and how static differs from instance members.