Home > front end >  Required init property with backing field gives null warning c# 11
Required init property with backing field gives null warning c# 11

Time:11-29

Having a required init property which sets a backing field still gives a null warning.

The below code gives a warning: Warning CS8618 Non-nullable field '_name' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

public class TestRequiredInit
{
    private readonly string _name;

    public required string Name
    {
        get => _name;
        init => _name = value;
    }
}

nullable warning on field

I don't see a way to create TestRequiredInit without _name being set to a non null value. different ways trying to create the class which all gives warnings or errors

Is this a bug in MSBuild / VS, or am I missing something?

Update to prevent people from recommending using an auto property

I simplified the code above a bit for the purpose of asking a question. I want to be able to add initialization logic to the property initializer.

public class TestRequiredInit
{
    private readonly string _name;

    public required string Name
    {
        get => _name;
        init
        {
            if (value.Length > 50)
            {
                throw new ArgumentException();
            }

            _name = value;
        }
    }
}

CodePudding user response:

There is no formal link between properties and their backing fields (if they even have any, which is not required), so the nullability of _name is by necessity analyzed in isolation of Name. What's more, while init setters are considered to happen as part of the construction phase (so they are allowed to do things like initialize other init properties) they are not formally part of construction for nullability analysis purposes -- which was correct up until the introduction of required, since there was no requirement to call them.

Nullability analysis could be extended to specifically consider init setters of required properties to be part of construction for analysis purposes, so the Name init setter would be considered to leave _name in a known non-null state, but getting this right is not trivial -- for example, because we can't assume any order in which the init setters are called, we should assume inside every init setter that fields might be null if the constructor doesn't definitely assign them not null, so we can give appropriate warnings. This is an inversion of the current semantics, where setters are allowed to assume fields are not null, since they can currently rely on the constructor having done so, gated by the existing warnings. It gets even hairier if the setter of a required property is not an init setter, since it might be called both during and after construction -- should we always warn just to be on the safe side?

All that and I haven't even considered how this interacts with derived classes. I'd definitely go with "this might be considered a bug, but formally defining the desired semantics and implementing them with as few surprises as possible is quite a bit of work, which has not yet been undertaken".

  • Related