Many classes in C# repeat the same pattern of defining a bunch of essential backing fields, then defining a constructor that takes values for those fields and assigns them. This is repetitive code that results in two definitions and an assignment for every parameter/field combination.
C# 12 primary constructors let you declare constructor parameters directly on the type. Those parameters are then in scope throughout the type body and can be used by properties, methods, and initializers.
Code
csharp
class Customer(string firstName, string lastName, DateOnly dateOfBirth)
{
public string FirstName => firstName;
public string LastName => lastName;
public DateOnly DateOfBirth => dateOfBirth;
}csharp
class Customer
{
private string firstName;
private string lastName;
private DateOnly dateOfBirth;
public Customer(string firstName, string lastName, DateOnly dateOfBirth)
{
this.firstName = firstName;
this.lastName = lastName;
this.dateOfBirth = dateOfBirth;
}
public string FirstName => firstName;
public string LastName => lastName;
public DateOnly DateOfBirth => dateOfBirth;
}Notes
- Primary constructor parameters are parameters, not fields or properties. The compiler only creates hidden storage when a member captures one, and that storage is mutable
- Using a parameter to initialize a property and also capturing it in a member stores the value twice, so the two can drift apart; the compiler warns about this (CS9124)
- Records C# 9.0 already had primary constructors; C# 12 brings them to every class and struct, without generating public properties