Primary constructors in their current state are horrible #7937
Replies: 4 comments 2 replies
-
The language does not guarantee that there will be any fields. |
Beta Was this translation helpful? Give feedback.
-
What would it mean for a parameter to be
You can assign the parameters from primary constructors to fields with whatever naming scheme you want, as enforceable by existing tools. The parameters themselves are not fields, they are parameters.
Non-record classes are different from record classes – record classes do more, by design. If they behaved the same, what would the point be of having both of them? |
Beta Was this translation helpful? Give feedback.
-
I think you're confusing primary constructor parameters for fields. The parameters are not guaranteed to become fields, but if you want fields, then you can always explicitly map them like you would for any other constructor: public class Sample(int foo)
{
private readonly int _foo = foo;
...
} This will ensure that you've mapped
public class Sample
{
private readonly int _foo;
private readonly IBarService _barService;
public Sample(int foo, IServiceProvider serviceProvider)
{
_foo = foo;
_barService = serviceProvider.GetRequiredService<IBarService>();
}
} In this example, public class Sample(int foo, IServiceProvider serviceProvider)
{
private readonly int _foo = foo;
private readonly IBarService _barService = serviceProvider.GetRequiredService<IBarService>();
} As this SharpLab snippet demonstrates: Primary constructors help us simplify our constructors and model definitions by giving us a way to extend the range available to their parameters. |
Beta Was this translation helpful? Give feedback.
-
Perhaps a source generator+analyzer could be created. The generator would take all (or a subset of) parameters and store them into backing fields following the desired naming convention ( // your code
[PrimaryConstructorToFields(NamingConvention = PrimaryConstructorNamingConventions.UnderscorePrefix)]
public partial class MyClass(int value)
{
public int GetValue =>
value; // WARNING: Do not use primary constructor parameters; Use `_value` instead.
}
// generated
partial class MyClass
{
private int _value = value;
} It could even get fancy and skip making fields for ones you've already made, or even make the ones it adds // your code
[PrimaryConstructorToFields(NamingConvention = PrimaryConstructorNamingConventions.MUnderscorePrefix)]
[PrimaryConstructorReadonlyFields(nameof(value))]
public partial class MyClass(string name, int value)
{
private string _name = name ?? throw new ArgumentNullException(nameof(name));
public string Name =>
_name;
public int Value =>
m_value;
}
// generated
partial class MyClass
{
private readonly int m_value = value;
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
We should be able to make parameters of primary constructors
protected
,private
orreadonly
. And possibly also enforce a consistent syntax, i.e._camelCase
for private fields,PascalCase
for protected/public fields.public class TellTale(private readonly string Id, readonly string Title);
public class ServiceA(private readonly IDependencyA, private readonly IDependencyB);
This would also address the inconsistency with classes where parameters of primary constructors are by default private and mutable, while with records they are public but immutable.
Beta Was this translation helpful? Give feedback.
All reactions