Replies: 7 comments 11 replies
-
Compared to primary constructors, direct parameters aren't that interesting. You still need to write all member declarations. While the latter can be accomplished cleanly by the former using the exact same amount of code (initialized member declarations), except that having members would be optional, which is in fact the case most of the time, unless you want a record which is separately available. To me, direct parameters look a little unwieldy and make the code actually harder to read, especially if mixed with normal parameters. On the other hand, primary ctors are already a familiar syntax and won't add a new concept to the language. A few features discussed are already covered by records which surprised me that they are brought up here. For instance, we're practically passed the casing problem because that only mattered for positional records which is already settled down. We don't need yet another mechanism to deal with parameter/member correspondence. |
Beta Was this translation helpful? Give feedback.
-
My main case for primary constructor is not setting lots of properties, but setting lots of fields. Must of my classes are either data classes or behaviour classes. Records already serve the use case of data classes, so we only need to consider behaviour classes. These very rarely have injected properties. However, I make heavy use of DI and so there are a lot of injected fields. For such use cases primary constructor are perfect, because they allow you to inject a new dependency by changing exactly one location. Direct constructors do not really help me that much- Now I need to repeat the name in 2 locations instead of 3, which isn't that great a saving. |
Beta Was this translation helpful? Give feedback.
-
Based on hearing @CyrusNajmabadi's explanation for the LDM's favoring of direct constructor parameters there are a number of issues at play here:
On the other hand the proposed approach provides limited benefit for both fields and properties. You still have to repeat the name in multiple locations, which isn't all that helpful. What we really want is having one, and exactly one, place where the member is defined. I still think going for option primary constructors is the best approach. I would rather have a really good solution to DI, then have an awkward solution for everything. However I also have another idea - consider this spaghetti against the wall. For consistency with records, the following generates public properties: class A(int X, string Y){} If I want to inject variables for use within the class, which are implicitly captured as needed, I declare them as variables: class A(var int x, var string y)
{
public override string ToString() => y + x; // used outside initialization, so capture x and y in fields.
} It's a bit odd as till now |
Beta Was this translation helpful? Give feedback.
-
This is while primary constructors already have a syntax and should be "relatively" simpler to design and implement? (and understand!) More importantly, primary constructors is more like a primitive construct, direct parameters are too specific to be usable at all outside their spec'ed semantics. I think if your needs is different than what records generate (which seems to be argument here; records but not records) For instance I need to use custom equality, non-init props, specific casing, and possibly custom getters: [SnowflakeRecord]
partial class C(int p); |
Beta Was this translation helpful? Give feedback.
-
Don't any members of the LDT ever consider Microsoft's other highly-successful language, TypeScript? It's had parameter properties since v1, released 8 years ago (wow has it been that long already!). The similar feature there is widely used and appreciated in that language, I don't see why it would be confusing in C#. class A {
constructor(public foo: number) { }
} |
Beta Was this translation helpful? Give feedback.
-
I'm absolutely crushed that the team is still not sold on the idea of primary constructors. A little bit of me dies inside every time I have to write something like this: public class OrdersController
{
private readonly IUserContext _userContext;
private readonly IOrderRepository _orderRepository;
private readonly ICrsfTokenValidator _tokenValidator;
private readonly IEncryptor _encryptor;
public OrdersController(
IUserContext userContext,
IOrderRepository orderRepository,
ICrsfTokenValidator tokenValidator,
IEncryptor encryptor)
{
_userContext = userContext;
_orderRepository = orderRepository;
_tokenValidator = tokenValidator;
_encryptor = encryptor;
}
// Methods here...
} This constructor simply should not be necessary. I hate writing them and reading them but in current C# there's nothing you can do about it. My only hope now is that required properties can step up to the plate; hopefully this will be allowed: public class OrdersController
{
public IUserContext UserContext { private get; required init; }
public IOrderRepository OrderRepository { private get; required init; }
public ICrsfTokenValidator TokenValidator { private get; required init; }
public IEncryptor Encryptor { private get; required init; }
// Methods here...
} Where by making the properties init-required but by hiding the getters you accomplish sort of the same goal of writing the (what are effectively) private readonly fields only once and still having them unchangeable after the class is constructed. It's not great; the syntax is still far too heavy, but at least it doesn't involve any repetition and I think the hiding space for bugs is significantly reduced. |
Beta Was this translation helpful? Give feedback.
-
This is the agenda for the C# Language Design Meeting held on October 21, 2020. The topics discussed in the meeting were Primary Constructors and Direct Parameter Constructors. Primary Constructors are a new feature in C# 9.0 that allow developers to define a constructor within a class definition using the 'init' keyword. This constructor can be used to set the initial values of properties in the class without having to define a separate constructor. Direct Parameter Constructors are a proposed feature that would allow developers to specify the values of parameters directly in the constructor call, rather than having to define the values as separate variables and then pass them into the constructor. This feature would simplify code and make it easier to understand. The proposal is still in the early stages of discussion, and no decision has been made yet on whether to include it in a future version of C#. |
Beta Was this translation helpful? Give feedback.
-
https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-21.md
Agenda
Beta Was this translation helpful? Give feedback.
All reactions