New C# 12 feature proves controversial: Primary constructors ‘worst feature I’ve ever seen implemented’

New C# 12 feature proves controversial: Primary constructors ‘worst feature I’ve ever seen implemented’

An official blog post describing primary constructors, a new feature in C# 12, has provoked developers to complain, with comments describing it such as “the worst feature I’ve ever seen implemented in C#.”

C# 12 was released as part of .NET 8.0, a long-term support release, in November 2023. Primary constructors already existed for record types, introduced in C# 9 three years ago, the idea being that developers could write:

public record Person(string FirstName, string LastName);

as a shortcut to declaring the properties and constructor separately. Public init-only properties, constructor and deconstructor are created automatically, where “init-only” means they can only be set during initialization of the record instance.

In C# 12 primary constructors were extended to classes and structs, though in this case parameters placed after the type name initialize private (not public) properties or fields. Assigning these values is compulsory. At first glance it looks like a handy feature to save writing some code and ensure that instances of the class are not created without setting these values.

Microsoft content developer David Pine wrote a post describing the benefits of the new feature, but comments have been largely unfavorable. One of the issues is that the automatically generated fields and properties are read-write, whereas often read-only members are required. In order to achieve this code must be added, defeating the purpose of simplification.

“I don’t use primary constructors, it just compacts code in a wrong way, said one comment. “the totally failed design to not have the auto-generated fields and properties readonly makes it fully unusable.”

C# lead designer Mads Torgersen was quick to respond, explaining that the decision to make primary constructor parameters mutable was a difficult one but was consistent because “every other parameter everywhere in C# is mutable (which I’m no fan of)”. He added that an annotation to specify read-only might be added in future but that “it’s more complicated than it sounds.”

Another developer remarked that what C# really needs is async constructors, which have not been implemented, the implication being that the team is focusing on the wrong things, primary constructors being a thing that “nobody needed.”

A third comment states that primary constructors are “probably the worst feature I’ve ever seen implemented in C# … easy to read and understand has always been the best part of c#. This goes completely against that.”

It is also inconsistent, said another, that “classes and records treat primary constructors differently,” since one makes private fields and properties, and the other public.

Microsoft had some advance warning that this feature would be controversial. The original proposal has 181 upvotes and 92 downvotes, around a 2-1 majority but suggesting considerable doubt. The first comment states that “I don’t think it offers any real power over current solutions, and only really benefits brevity, at the cost of significant new rules and unfamiliar syntax. C# is a complex language as it is, and we should reserve additional complexity for where it can make a real difference.”

There is of course an option not to use the feature. It is not intended for all use cases, but rather for the “90% (often higher) where the defaults suffice just fine … it’s just more pleasant to have the simple form,” said another comment to the proposal.

Some developers then do like the primary constructors feature and will use it for the benefit of brevity, when it does what they require. That also means that the feature is here to stay, since removing or changing it in future would break code. It is inherent to language design that new features can be added, but are hard to take away, which is why programming languages tend to become more complex as they mature, despite the best intentions of those who maintain them.