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;
}
}
I don't see a way to create TestRequiredInit
without _name
being set to a non null value.
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".