Auto-Implemented Properties in C# Explained
Auto-implemented properties in C# provide a concise syntax for declaring class properties without needing to explicitly define a private backing field. This article explains how auto-implemented properties work, their syntax, how to initialize them, control their access levels, and when to choose them over traditional properties.
The Purpose of Auto-Implemented Properties
In object-oriented programming, encapsulation is typically achieved using getters and setters to control access to class fields. In older versions of C#, developers had to manually declare a private backing field alongside public getter and setter methods or full property syntax.
Auto-implemented properties streamline this by allowing you to declare a property in a single line. When the C# compiler encounters an auto-implemented property, it automatically creates a hidden, private backing field that can only be accessed through the property's accessors.
Basic Syntax Comparison
Traditional Property with Backing Field:
public class User
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}Auto-Implemented Property:
public class User
{
public string Name { get; set; }
}Both examples produce functionally identical code after compilation, but the auto-implemented syntax eliminates boilerplate code.
Property Initializers
You can initialize auto-implemented properties with default values directly in the declaration:
public class Product
{
public string Name { get; set; } = "Unnamed Product";
public decimal Price { get; set; } = 0.0m;
}These default values are assigned when an instance of the class is constructed.
Read-Only and Init-Only Properties
Auto-implemented properties support immutability using read-only
accessors or the init accessor.
- Read-only properties: By omitting the
setaccessor, the property can only be set via the declaration initializer or within the class constructor.
public class Order
{
public Guid Id { get; } = Guid.NewGuid();
public Order(Guid customId)
{
Id = customId; // Allowed in constructor
}
}- Init-only properties (C# 9.0+): Using
initallows the property to be assigned only during object initialization:
public class Customer
{
public int CustomerId { get; init; }
}
// Usage
var customer = new Customer { CustomerId = 101 };
// customer.CustomerId = 102; // Compilation errorAccess Modifiers on Accessors
You can restrict the visibility of the get or
set accessor independently by adding access modifiers:
public class BankAccount
{
public decimal Balance { get; private set; }
public void Deposit(decimal amount)
{
if (amount > 0)
{
Balance += amount;
}
}
}In this case, any external code can read Balance, but
only code inside the BankAccount class can modify it.
When to Use Auto-Implemented Properties
Auto-implemented properties are best used when:
- No custom logic or validation is needed in the
getorsetaccessors. - You are building Data Transfer Objects (DTOs), models, or entity types.
- You want clean, readable code with minimal boilerplate.
If you need to validate input (such as throwing an
ArgumentOutOfRangeException), trigger change notification
events (like INotifyPropertyChanged), or transform values
before storage, use a full property with an explicit backing field
instead.