← Back to blog
28 August 2022 · 7 min read

C# 11 Required Members, the imperfectly awesome feature

If you skim the C# 11 feature list, there's one that grabs the attention as a yellow Lamborghini in a parking lot (except Monaco parking lots 💰). It's Required Members. The most wanted from the list.

Is it exciting? Yes! Is it perfect? Not sure. Stay till the end to see why.

🤨 What are we trying to solve here?

Constructors are super handy but can be painful. They are positional, so brittle to changes. Adding a new optional member requires not only a new overload but also making sure that members are added at the end of the list. No one wants to break all consumers. Am I right?

You may say: "let's avoid constructors and take advantage of object Initializers and Nullable Reference Types."

And I quickly answer: "Calm down, my friend!"

Constructors are still important, and nullable reference types have a weak spot at Initialization. Even with the investment to make object Initializers better through the "init" keyword.

What's the weak spot?

👋 Say Hi to Required Members

Required Members come to solve that. Since C# 1.0 there's no expressive way to declare a member as Required. We are now getting it.

public class User
{
	public required string Email { get; init; }
}

var user = new User()
{
	Email = "gui@guiferreira.me"
};

Not only do you get an expressive way to annotate your models, but non-nullable warnings go away.

The goal is to annotate fields as well, not just properties. That's why it's named Required Members instead of Required Properties. In case you asked it.

With Required Members, the compiler will enforce that you initialize that member. You can use it on Classes, Records or Structs.

error CS9035: Required member 'User.Email' must be set in the object initializer or attribute constructor.

Please keep in mind that Required will not enforce an explicit initialization to a non-null value. Nullable and required are independent concerns. It's up to you as a developer to enforce it.

❓ So, what's the problem with it?

If you remember, I started this article by saying that Required Members isn't perfect. The success of a feature is highly related to its adoption. And here, you can find some things that may impact it.

using System.Diagnostics.CodeAnalysis;

public class User
{
	[SetsRequiredMembers]
	public User(string email)
	{
		Email = email;
	}

	public required string Email { get; init; }
	public string? Name { get; init; }
}

var user = new User("gui@guiferreira.me");

Evolving a language with more than 20 years isn't easy. Each step should be pondered and carefully evaluated. We have seen that in Nullable Reference Types. I believe that it also influenced the design of Required Members.

⏩ What's now?

Am I excited about this feature? Yes, I am. 🤩 I will be using it for sure.

Unfortunately, not as much as I first suspected. Nowadays, most of my Data Transfer Objects (DTOs) are records, and in my Domain, you will find more than variables being assigned in the constructor.

I'm curious to see if this is a stepping stone in the language and see what the community will be developing on top of it.

Let me know what you think about it, follow me on Twitter (@gsferreira), and let's keep in touch.

Developer Insights

What I'm building, learning, and discovering each week.

By signing up, you'll get my free weekly newsletter plus occasional updates about my courses. You can unsubscribe anytime.