Non-nullable properties in C# 11
Aleksei Zagoskin
Posted on January 14, 2023
After taking a break from blogging, I am excited to be back and try something new. As an experiment, I have decided to focus on writing shorter articles, which hopefully, will allow me to share some of my thoughts, ideas and tips in a more concise and digestible manner. Let's see how it goes. Shall we?
Problem
First, take a look at this simple code:
public record User
{
public string Name { get; init; }
public string? Email { get; init; }
}
Nothing fancy here, an immutable record with two properties: Name
and Email
. At first glance, it may look fine, but the compiler won't like this code:
Program.cs(14, 19): [CS8618] Non-nullable property 'Name' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
This means that we created an immutable record with a non-nullable property Name
, but nothing will stop us from creating a new user and not providing any name at all:
var user = new User { Email = "Sam" };
Solution 1: Assign default!
(Don't do that) Often, to shut the compiler up, programmers assign default values with an exclamation mark to such properties:
public record User
{
public string Name { get; init; } = default!; // or null! or ""
public string? Email { get; init; }
}
Here we simply ask the compiler to ignore the issue, while the problem remains: we are still able to create an instance of that record and forget to assign a value to Name
.
💩 Solution 1: Constructor
public record User
{
public string Name { get; }
public string? Email { get; init; }
public User(string name, string? email = default)
{
Name = name;
Email = email;
}
}
Very boring and verbose code, which at the end of the day does the job. There is no way a developer can forget to pass a value for Name
because now it's a mandatory constructor parameter.
Solution 2: Positional properties
public record User(string Name, string? Email = default);
In this case whenever we create a new instance of the User
type, we have to provide a value for the Name
property. Nice and clean.
Solution 3: required
modifier
The new keyword required
was introduced in C# 11, which can be applied to properties of classes, records and structs. You can find all details as well as information about existing limitations here.
public record User
{
public required string Name { get; init; }
public string? Email { get; init; }
}
Problem solved.
I hope it helps and thank you for reading!
Cheers!
Posted on January 14, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.