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

Time:12-21

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?

CodePudding user response:

init properties do not force the values to be initialized, only constructors do. What init does is that, if the property is to be initialized, it must be done at construction time in an object initializer (or in the constructor if you have one): it does not guarantee that it will.

If you want maximum robustness here, initialize them through the constructor instead, which allows you to add guard clauses and guarantee non-nullable properties.

This is what you want (and I do as well):

This proposal adds a way of specifying that a property or field is required to be set during object initialization, forcing the instance creator to provide an initial value for the member in an object initializer at the creation site.

  • Related