C# > Language Features by Version > C# 6 to C# 12 Highlights > Init-only Properties (C# 9)
Init-Only Properties in C# 9
C# 9 introduced init-only properties, providing a way to initialize properties during object creation but preventing modification afterward. This enhances object immutability and improves code clarity.
Basic Init-Only Property
The init
keyword allows a property to be set only during object initialization. Once the object is created, the property becomes read-only. Attempting to modify an init-only property after initialization results in a compile-time error.
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
public override string ToString()
{
return $"FirstName: {FirstName}, LastName: {LastName}";
}
}
public class Example
{
public static void Main(string[] args)
{
Person person = new Person { FirstName = "John", LastName = "Doe" };
Console.WriteLine(person.ToString());
// Compilation error: Cannot modify init-only property after object creation
// person.FirstName = "Jane";
}
}
Concepts Behind Init-Only Properties
Init-only properties bridge the gap between fully mutable and immutable objects. They allow for object customization during creation while guaranteeing that certain key properties remain constant throughout the object's lifecycle. This contributes to better object state management and thread safety.
Real-Life Use Case
Consider a configuration object where certain settings should only be defined during application startup. Using init-only properties ensures that these configurations are not accidentally modified during runtime, preventing unexpected behavior. For example a connection string, an API Key or some external configuration setting.
Best Practices
Interview Tip
Be prepared to explain the difference between get; set;
, get; private set;
, and get; init;
properties. Understand the use cases for each and the benefits they provide in terms of encapsulation and immutability.
When to Use Them
Use init-only properties when you need to initialize a property during object creation and then prevent further modification. This is particularly useful for configuration settings, identifiers, or any data that represents a fixed characteristic of an object.
Memory Footprint
Init-only properties do not introduce any additional memory overhead compared to regular properties. They simply enforce a restriction on when the property can be set. The underlying storage is the same.
Alternatives
Before C# 9, you could achieve similar behavior using a constructor to set the property value and then only providing a getter. However, this approach is less discoverable and doesn't clearly communicate the intent that the property is only meant to be initialized during object creation. Another older alternative involved private setters and setting the values in the constructor. The key advantage with init is the object initializer syntax.
Pros
Cons
Example with Record Type
Records in C# are inherently immutable. init
properties work perfectly with records to allow initialization using object initializer syntax. This provides a concise and safe way to create immutable data objects.
public record PersonRecord
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
public class ExampleRecord
{
public static void Main(string[] args)
{
PersonRecord person = new PersonRecord { FirstName = "John", LastName = "Doe" };
Console.WriteLine($"FirstName: {person.FirstName}, LastName: {person.LastName}");
}
}
FAQ
-
What is the difference between
get; set;
andget; init;
?
get; set;
allows a property to be both read and written at any time.get; init;
allows a property to be read at any time, but it can only be written during object initialization. -
Can I use init-only properties in older versions of C#?
No, init-only properties are a feature introduced in C# 9 and are not available in earlier versions. -
Are init-only properties truly immutable?
Init-only properties prevent direct modification of the property itself after initialization. However, if the property holds a reference to a mutable object (e.g., aList
), the contents of that object can still be changed. To achieve true immutability, the object itself must be immutable.