init accessors in C#
In C#, we generally declare a property as below:
// Property with a getter and setter
public class ClassName{
public datatype propertyName { get; set; }
}
// Read-only Property with only a getter
public class ClassName{
public datatype propertyName { get; }
}
Read-only property values must be set when the object is initialized from the class, and this is achieved in the constructor of the class.
public ClassName(datatype propertyValue){
propertyName = propertyValue;
}
These properties are immutable, means they cannot be changed once created.
C# 9 introduced the init only setter for a property. An init only property is also called as an indexer.
// Property with a getter and init accessor
public class ClassName{
public datatype propertyName { get; init; }
}
An init property is settable in a local function or lambda in the following circumstances:
- During an object initializer
var s = new Student(){
FirstName = “Tim”,
LastName = “Smith”,
};
- During a with expression initializer
- Inside an instance constructor of the containing or derived type, on this or base
class Base{
public bool Value { get; init; }
}
class Derived : Base{
Derived(){
// Not allowed with get only properties but allowed with init
Value = true;
}
}
class Consumption{
void Example(){
var d = new Derived() { Value = true; };
}
}
- Inside the init accessor of any property, on this or base
- Inside attribute usages with named parameters
- The properties can be validated in the init accessors as below:
public class Person
{
private readonly string firstName = “<unknown>”;
private readonly string lastName = “<unknown>”;
public string FirstName {
get => firstName;
init => firstName = (value ?? throw new ArgumentNullException(nameof(FirstName)));
}
public string LastName {
get => lastName;
init => lastName = (value ?? throw new ArgumentNullException(nameof(LastName)));
}
}
References: