Should `required` on a property force it to be nullable in the constructor always
Today, when decide the state of all properties at the start of a constructor, we assume that all properties from the base type have been initialized by the chained constructor. However, this might not be true of required properties. Consider the following scenario:
#nullable enable
public class Base
{
public required string Prop1 { get; set; }
}
public class Derived : Base
{
public required string Prop2 { get; set; }
[SetsRequiredMembers]
public Derived(int unused) : base()
{
Prop1.ToString(); // Warning?
Prop2.ToString(); // Warning: possibly null dereference
} // Warning that Prop2 has a maybenull value. Does Prop1 get a warning?
}
Prop1 is an auto-implemented property, but we might not always know that this is the case. From source, this is relatively easy to detect, but if Base is defined in metadata then this becomes much harder to detect.
I propose that required is enough of an indicator for the purposes of nullable analysis that we should make the initial state of properties marked required default(PropertyType), regardless of whether the property is known to be an auto-property or not.
Is Prop1 being auto-implemented even relevant here?
required means it is set after construction, so in Derived ctor Prop1 is definitely maybe null (unless Base ctor is SetsRequiredMembers, which it isn't in your code snippet). So, I think yes, there should be a warning in Derived ctor for Prop1.
Discussed in LDM.
We accept the following rules:
When chaining to a constructor that does not have SetsRequiredMembersAttribute, all required members have a null state of default(T), including those required members from a base type. At the end of a constructor that is attributed with SetsRequiredMembersAttribute, all required members must have the null state they are declared with, including those required members from a base type.