Search code examples
c#nullable-reference-typesc#-10.0

Init-only reference properties with nullable enabled in C# 10.0


I tried to use init-only properties to force client code to initialize my class when they create it, but without a constructor. It's not working as I planned.

Here's the class, stripped down to illustrate the point.

public class Target
{
    public int              Id               { get; init; }
    public string           Name             { get; init; }
}

The project is on .NET 6.0 so I'm using C# 10.0. Nullable is set to "Enabled" on the project so the reference property Name must be non-null. What confuses me is that that compiler complains that the Name property could be null after the constructor.

CS8618: Non-nullable property 'Name' must contain a non-null value when exiting constructor

This is true, of course, but the whole point of using an init-only property was that I don't want a constructor. I want to force people to use the init-only properties to initialize Name to something valid. If I wanted to write a constructor, I could just write a read-only property.

(I realize I could default Name to string.Empty or some other valid value myself but I want to force the coder to do that)

Does C# 10.0 give me a way to achieve what I want without doing any of the following?

  • defaulting a reference property to some non-null value (either by constructor or by initializer inline)
  • declaring the property as nullable
  • disabling nullable altogether
  • use a record type instead of a class (because I want member functions)

Is this doable?

My searching on this topic led me to this post but the best I could get from it was a link to Mads Torgensen's blog discussing what they were planning to do in C# 10. Is there an update on it?


Solution

  • This is possible starting with C# 11 / .net 7 using the required keyword. For example:

    public class Target
    {
        public int Id { get; init; }
        public required string Name { get; init; }
    }
    

    Relevant section from the C# 11 release notes: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required

    Keyword documentation: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required