Auto-Properties - Simplifying Property Declarations in C#
Vaibhav • September 10, 2025
In the previous article, we explored property accessors - how get
and set
allow you to control access to object state, enforce validation, and expose
computed values. Now, we turn to a feature that simplifies property declarations when no custom logic is needed:
auto-properties.
Auto-properties are a concise way to declare properties that simply store and retrieve values. They reduce boilerplate code, improve readability, and are widely used in modern C# applications. In this article, we’ll explore how auto-properties work, when to use them, how they relate to encapsulation, and how to extend them when custom logic becomes necessary.
What Are Auto-Properties?
An auto-property is a shorthand syntax for declaring a property with an implicit backing field. Instead of writing a full property with a private field and explicit accessors, you let the compiler generate the field for you.
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
This is equivalent to:
public class Product
{
private string name;
private decimal price;
public string Name
{
get { return name; }
set { name = value; }
}
public decimal Price
{
get { return price; }
set { price = value; }
}
}
The auto-property version is much cleaner and easier to read. The compiler automatically creates a hidden field to
store the value, and the get
and set
accessors
work as expected.
Auto-properties are ideal when you don’t need custom logic in the accessors. They provide a clean and efficient way to expose data while maintaining encapsulation.
Using Auto-Properties
You can use auto-properties anywhere you would use a regular property. They are especially useful in data models, configuration classes, and DTOs (Data Transfer Objects).
public class User
{
public string Username { get; set; }
public string Email { get; set; }
public DateTime RegisteredAt { get; set; }
}
This class defines three auto-properties. You can read and write them just like regular properties:
User u = new User();
u.Username = "vaibhav";
u.Email = "[email protected]";
u.RegisteredAt = DateTime.Now;
The compiler handles the storage and retrieval behind the scenes. You don’t need to write any additional code.
Read-Only Auto-Properties
Starting with C# 6, you can create read-only auto-properties by omitting the set
accessor and initializing the property in the constructor or inline.
public class User
{
public string Username { get; }
public DateTime RegisteredAt { get; }
public User(string username)
{
Username = username;
RegisteredAt = DateTime.Now;
}
}
These properties can be set only during object construction. After that, they are read-only. This is useful for values that should not change once initialized.
Use read-only auto-properties for immutable data. This improves safety and clarity, especially in multi-threaded or domain-driven applications.
Init-Only Auto-Properties
C# 9 introduced init-only setters, which allow properties to be set only during object initialization. This provides a middle ground between read-only and fully mutable properties.
public class User
{
public string Username { get; init; }
public string Email { get; init; }
}
You can set these properties using object initializer syntax:
User u = new User
{
Username = "vaibhav",
Email = "[email protected]"
};
After initialization, the properties become read-only. This pattern is useful for creating immutable objects with flexible initialization.
Init-only properties require C# 9 or later and are supported only in .NET 5 and newer versions.
Default Values for Auto-Properties
You can assign default values to auto-properties directly in their declaration. This ensures that the property has a meaningful value even if not explicitly set.
public class Settings
{
public string Theme { get; set; } = "Light";
public int FontSize { get; set; } = 12;
}
When you create a new Settings
object, these properties will have default values:
Settings s = new Settings();
Console.WriteLine(s.Theme); // Output: Light
Console.WriteLine(s.FontSize); // Output: 12
This pattern is useful for configuration classes and user preferences.
Combining Auto-Properties with Access Modifiers
You can apply different access modifiers to the get
and set
accessors of an auto-property. This allows you to expose one accessor publicly and
restrict the other.
public class Configuration
{
public string AppName { get; private set; } = "MyApp";
}
In this example, AppName
can be read publicly but only set within the class. This
is useful for values that should be initialized once and then remain unchanged.
When Not to Use Auto-Properties
Auto-properties are convenient, but they are not suitable when you need:
- Validation logic in the
set
accessor. - Computed values based on other fields.
- Custom behavior when getting or setting the value.
In such cases, use full properties with explicit accessors and backing fields. For example:
private decimal price;
public decimal Price
{
get { return price; }
set
{
if (value < 0)
throw new ArgumentException("Price cannot be negative.");
price = value;
}
}
This allows you to enforce rules and maintain object integrity.
You can start with auto-properties and later convert them to full properties if your requirements change. This makes auto-properties a great starting point for evolving designs.
Auto-Properties and Encapsulation
Auto-properties support encapsulation by hiding the backing field and exposing a controlled interface. Even though the field is generated automatically, it is still private and inaccessible from outside the class.
This means you can change the internal implementation later without affecting external code. For example, you might replace an auto-property with a computed property or add validation logic.
Summary
Auto-properties are a powerful feature in C# that simplify property declarations and reduce boilerplate code. They are ideal for exposing data without custom logic, and they support encapsulation by hiding the backing field. You can use auto-properties with default values, read-only or init-only access, and custom access modifiers.
We explored how auto-properties work, when to use them, and how to extend them when needed. We also discussed their role in object initialization, configuration, and data modeling.
As you continue building classes in C#, auto-properties will help you write cleaner, more expressive code. Use them thoughtfully, and switch to full properties when your design requires more control.
In the next article, we’ll explore Object Initialization - how to create and configure objects using constructors, initializers, and patterns that promote clarity and consistency.