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!
Top comments (3)
Great sir, your this article motivated me to switch from C# 10 to C# 11, means from .Net 6 to .Net 7, thanks a lot.
Thank you for the feedback, I'm glad you found the article useful!
Nice article.