Introducing C# 12: Primary constructor on classes and struct
Introduction
.NET 8 and C# 12 are available in preview and I’m glad to share with you the novelties they bring. If you remember C# 9 features, you probably noticed the feature Primary constructors available only with records. If you don’t remember, or don’t know at all what they are, I suggest you to read my post on this topic: https://anthonygiretti.com/2020/06/17/introducing-c-9-records/.
Now you are familiar with them, I can introduce you the new C# 12 feature: the availability of the primary constructors on classes and structs in this article.
Primary constructor on classes
Primary constructors work differently with classes. If you check again my previous article on them in the introduction, you noticed they weren’t any body on the primary constructor. On classes, a body is mandatory, since you omit it like records, the instance will be empty. On records, properties will automatically filled as follow:

You can notice to empty Product object when Product is a regular class:

Like records, since you declare a primary constructor, you MUST use it when you declare explicit constructors as follow:
var product1 = new Product(); | |
var product2 = new Product("Basic"); | |
var product3 = new Product("My product", 1); | |
public class Product(string name, int categoryId) | |
{ | |
public Product() : this("Default", -1) { } | |
public Product(string name) : this(name, 0) {} | |
public string Name => name; | |
public int CategoryId => categoryId; | |
public string ProductId => $"{name}-{categoryId}"; | |
} |
As you can see, it requires the this() keyword, which invokes the primary constructor. If you omit it, the compiler will raise the following issue error message:
Error CS8862 A constructor declared in a type with parameter list must have ‘this’ constructor initializer.
Note: It is possible to combine primary constructors, constructors without parameters, constructors with parameters, and fields initializers as follow:
public class Product(string name, int categoryId) | |
{ | |
public Product() : this("Default", -1) { ProductDescription = "InvalidProductId"; } | |
public Product(string name) : this(name, 0) { } | |
public string Name => name; | |
public int CategoryId => categoryId; | |
public string ProductDescription { get; private set; } | |
} |
That’s it for the Primary constructors on classes !
Primary constructor on structs
Behavior is the same, we already had a similar syntax on record struct with parameterless constructor brought by C# 11, here is my post on it for as a reminder: https://anthonygiretti.com/2022/02/21/introducing-c-10-structs-parameterless-constructor-and-instance-field-initializer/
That’s it !