Object Initialization - Creating and Configuring Instances in C#
Vaibhav • September 10, 2025
In the previous article, we explored auto-properties - a concise way to declare properties that store and retrieve values without writing explicit backing fields. Now, we shift our focus to a closely related topic: object initialization. This article explores how objects are created and configured in C#, using constructors, object initializers, and patterns that promote clarity, consistency, and maintainability.
Object initialization is the process of assigning values to an object’s fields and properties when it is created. A well-initialized object starts life in a valid state, ready to perform its intended behavior. In this article, we’ll examine different ways to initialize objects, how they relate to encapsulation and constructors, and how to choose the right approach depending on your design goals.
Creating Objects with Constructors
The most common way to initialize an object is by using a constructor. A constructor is a special
method that runs automatically when an object is created using the new
keyword.
public class User
{
public string Username { get; }
public DateTime RegisteredAt { get; }
public User(string username)
{
Username = username;
RegisteredAt = DateTime.Now;
}
}
This class defines a constructor that takes a username
and sets the RegisteredAt
property to the current time. When you create a new User
, the constructor ensures that both properties are initialized:
User u = new User("vaibhav");
Constructors are ideal when certain values are required for the object to function correctly. They enforce initialization rules and prevent incomplete or invalid objects.
Use constructors to enforce required values. If an object cannot function without certain data, make those values mandatory in the constructor.
Using Object Initializers
For classes with public properties and a parameterless constructor, C# provides a convenient syntax called object initializer. This allows you to set properties directly at the time of creation.
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
You can initialize a Product
like this:
Product p = new Product
{
Name = "Laptop",
Price = 999.99m
};
This syntax is clean and readable. It’s especially useful for configuration objects, test data, and scenarios where you want to set multiple properties at once.
Object initializers work only with properties that have public set
accessors or
init
accessors. They do not work
with read-only properties.
Combining Constructors and Initializers
You can combine constructors and object initializers to set both required and optional values. This provides flexibility while still enforcing core requirements.
public class User
{
public string Username { get; }
public string Email { get; set; }
public DateTime RegisteredAt { get; }
public User(string username)
{
Username = username;
RegisteredAt = DateTime.Now;
}
}
You can initialize a User
like this:
User u = new User("vaibhav")
{
Email = "[email protected]"
};
This pattern is useful when some values are required and others are optional. It keeps the constructor focused and avoids overloading it with too many parameters.
Init-Only Properties for Immutable Objects
C# 9 introduced init-only properties, which allow properties to be set only during object initialization. After that, they become read-only.
public class Settings
{
public string Theme { get; init; }
public int FontSize { get; init; }
}
You can initialize a Settings
object like this:
Settings s = new Settings
{
Theme = "Dark",
FontSize = 14
};
After initialization, the properties cannot be changed. This pattern supports immutability and is ideal for configuration and domain models.
Init-only properties require C# 9 or later and are supported in .NET 5 and newer versions.
Initializing Collections
You can initialize collections using collection initializers. This allows you to add items at the time of creation.
List<string> fruits = new List<string>
{
"Apple",
"Banana",
"Cherry"
};
This syntax is concise and expressive. It’s useful for test data, default values, and configuration lists.
You can also initialize dictionaries:
Dictionary<string, int> scores = new Dictionary<string, int>
{
["Alice"] = 90,
["Bob"] = 85
};
This pattern is supported by collection types that implement ICollection<T>
or IDictionary<K,V>
.
Initializing Nested Objects
You can use object initializers to configure nested objects. This is useful for building complex structures in a readable way.
public class Address
{
public string City { get; set; }
public string Country { get; set; }
}
public class User
{
public string Username { get; set; }
public Address Location { get; set; }
}
You can initialize a User
with a nested Address
like this:
User u = new User
{
Username = "vaibhav",
Location = new Address
{
City = "Pune",
Country = "India"
}
};
This syntax is readable and expressive. It’s commonly used in configuration files, test setups, and UI models.
Avoiding Incomplete Initialization
One risk with object initializers is that they can leave objects in an incomplete or invalid state. To avoid this, use constructors for required values and restrict access to critical properties.
public class Invoice
{
public string Id { get; }
public decimal Amount { get; set; }
public Invoice(string id)
{
Id = id;
}
}
This design ensures that every Invoice
has a valid Id
. Optional values like Amount
can be set later.
Use constructors to enforce required values and object initializers for optional configuration. This keeps your objects safe and flexible.
Summary
Object initialization is a fundamental part of working with classes in C#. It determines how objects are created, configured, and prepared for use. We explored constructors for enforcing required values, object initializers for flexible configuration, init-only properties for immutability, and collection initializers for building structured data.
We also discussed how to combine constructors and initializers, initialize nested objects, and avoid incomplete states. These patterns help you write code that is clear, consistent, and aligned with object-oriented principles.
As you continue building applications, choose the initialization strategy that best fits your design goals. Constructors provide safety, initializers provide flexibility, and init-only properties provide immutability. Together, they form a powerful toolkit for creating robust and maintainable objects.
In the next article, we’ll explore this Keyword - how to refer to the current object instance and resolve naming conflicts in constructors, methods, and properties.