C# Init Only and Required Properties
Tags: programming, csharp, softwaredevelopment, dotnet
Published: 2024-04-19 19:38:30

---
title: C# Init Only and Required Properties
published: true
date: 2024-04-10 11:02:07 UTC
tags: programming,csharp,softwaredevelopment,dotnet
canonical_url: https://antondevtips.com/blog/csharp-init-only-and-required-properties
---

### Init only properties

C# 9.0 introduced a new type of a property accessor called **init**.  
The **init** only property can be assigned only during object creation and can’t be changed further. This enforces immutability.

Let’s see how to define **init** only properties:

```csharp
public record Product
{
    public int Id { get; init; }

    public string Name { get; init; }
    
    public decimal Price { get; init; }
}
    
// Create an instance of Product's record
var product = new Product
{
    Id = 1,
    Name = "Phone",
    Price = 500.00m
};
```

The best practise when creating a record is declaring all of its properties as **init** only. This ensures that properties can’t be changed, ensuring the immutability of the record’s data. Although you can define **init** properties in a **class**  too.

**init** only properties have the same behaviour as **set** properties. You can use a backing field for the property if needed:

```csharp
public record Product
{
    private readonly decimal _price;

    public required decimal Price
    {
        get => _price;
        init => _price = value;
    }
    
    // Other properties...
}
```

### Required properties

A new keyword called **required** was introduced in C# 11, which is a great addition to **init** only properties:

```csharp
public record Product
{
    public required int Id { get; init; }

    public required string Name { get; init; }
    
    public required decimal Price { get; init; }
}
```

This ensures that all properties marked with **required** keyword, should be assigned when creating an object, otherwise a compilation error is raised:

```csharp
// This code doesn't compile as Price property is not assigned
var product = new Product
{
    Id = 1,
    Name = "Phone"
};
```

**init** and **required** keywords make a great pair together. **required** ensures that **init** only properties are assigned during objection creation, as these properties can’t be changed further.

### Positional Records

C# also provides a shortened form of record declaration:

```csharp
public record Product(int Id, string Name, decimal Price);

var product = new Product(1, "PC", 1000.00m);
```

A single line of code! We assign all the properties using a record’s constructor which is called a **primary** constructor. Under the hood this code is translated to a classic form of a record declaration with all properties being **init** only. This form of record is also called a **positional record** as all properties under the hood are created in the exact order as their position in the primary constructor. Positional form of declaration looks really elegant and concise when a record doesn’t have a lot of fields.

When creating a record’s object using a primary constructor — you are forced to assign all the properties. Though the **required** keyword is not used here.

### Init Only and Required Properties Important Notes

#### 1. Required keyword only works at compile time

When an object is created at the runtime, **required** keyword has no effect, it doesn’t throw exceptions even if the field is not assigned with a value. **required** works only at compile time. Although there is one exception: objects serialized and deserialized using System.Text.Json in **NET 8** can throw exceptions when **required** properties are not assigned with a value.

#### 2. Nullable properties can be marked as required

It is perfectly fine to mark nullable properties as required. It forces you to assign it a real value or null when creating an object. Let’s add a nullable Description property to the Product record:

```csharp
public record Product
{
    public required int Id { get; init; }

    public required string Name { get; init; }
    
    public required string? Description { get; init; }
    
    public required decimal Price { get; init; }
}
    
var product = new Product
{
    Id = 1,
    Name = "PC",
    Price = 1000.00m,
    Description = "Some amazing PC" // Assign some value
};

var product2 = new Product
{
    Id = 1,
    Name = "PC",
    Price = 1000.00m,
    Description = null // Explicitly assign null here
};
```

You should really consider using **required** keyword for all types of properties whenever appropriate.

### 3. Using constructor with required properties

Let’s see the following code where we create a class with required properties and a constructor:

```csharp
public class User
{
    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }
    
    public required string Name { get; init; }
    
    public required int Age { get; init; }
}
    
var user = new User("Anton", 30); // This doesn't compile
```

This code doesn’t compile as compiler tells that required properties are not assigned, even if they are assigned from the constructor. To fix the code you need to add property assignments along with the constructor:

```csharp
var user = new User("Anton", 30)
{
    Name = "Anton",
    Age = 30
}; // Now this compiles
```

This one is a real caveat and you should consider this strange behaviour when modelling classes.

Hope you find this blog post useful. Happy coding!

_Originally published at_ [_https://antondevtips.com_](https://antondevtips.com/blog/csharp-init-only-and-required-properties)_._

### After reading the post consider the following:

- [Subscribe](https://antondevtips.com/blog/csharp-init-only-and-required-properties#subscribe) **to receive newsletters with the latest blog posts**
- [Download](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/backend/CSharp/CSharp9_InitOnly) **the source code for this post from my** [github](https://github.com/AntonMartyniuk-DevTips/dev-tips-code/tree/main/backend/CSharp/CSharp9_InitOnly) (available for my sponsors on BuyMeACoffee and Patreon)

If you like my content —  **consider supporting me**

Unlock exclusive access to the source code from the blog posts by joining my **Patreon** and **Buy Me A Coffee** communities!

[![](https://cdn-images-1.medium.com/max/233/1*GSZFx05RDUWr5pn_E9bK8w.png)](https://www.buymeacoffee.com/antonmartyniuk)

[![](https://cdn-images-1.medium.com/max/229/1*8tJk9eYCJrkzoAJw2cILSA.png)](https://www.patreon.com/bePatron?u=73769486)

* * *