-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Avoid synthesizing parameterless struct constructors
- Proposed
- Prototype: Not Started
- Implementation: Not Started
- Specification: Not Started
Summary
Avoid synthesizing a parameterless constructor for struct
types; run field initializers from declared constructors only;
and report an error if the struct
declaration includes field initializers but no constructors.
Motivation
With C#10, if a struct
type declaration includes field initializers but no constructors, the compiler will synthesize a parameterless constructor that will run the field initializers.
The compiler does not synthesize a parameterless constructor if there are explicit constructors because,
with record struct
types, the field initializers are bound in the context of the primary constructor so the synthesized parameterless constructor would need to invoke the primary constructor to run the field initializers. But what values should be passed for the primary constructor arguments?
The fact that a parameterless constructor is synthesized in some cases but not all makes it difficult to understand when new()
is equivalent to default
, and it means the result of new()
can change silently when non-default constructors are added or removed.
// With no constructors
struct S
{
public int Value = 42;
}
WriteLine(new S().Value); // 42
// After adding non-default constructor
struct S
{
public int Value = 42;
public S(string message) { }
}
WriteLine(new S().Value); // 0
If instead, struct
constructors are never synthesized, then the behavior is simplified:
- Parameterless constructors can be declared explicitly.
- Field initializers are run from declared constructors only.
- Unless the
struct
type declares a parameterless constructor,new()
is equivalent todefault
, consistent with C#9 and before.
Detailed design
Never synthesize a parameterless constructor for struct
types.
Report an error if a struct
type declaration includes field initializers but no explicit constructors.
// With no constructors
struct S
{
public int Value = 42; // error: containing type 'S' has no declared constructor
}
WriteLine(new S().Value); // error above
// After adding parameterless constructor
struct S
{
public int Value = 42;
public S() { }
}
WriteLine(new S().Value); // 42
// After adding non-default constructor instead
struct S
{
public int Value = 42;
public S(string message) { }
}
WriteLine(new S().Value); // 0
Drawbacks
It is a breaking change from C#10 to require an explicit constructor if there are field initializers, but it's not a silent break (an error is reported), and the fix is simple (add an empty parameterless constructor).