OpenAPITools / OpenAPITools/openapi-generator

[REQ] [C#] Replace constructors with required init-only properties

Open
#17,147 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement: Feature
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Is your feature request related to a problem? Please describe.

Constructors are dangerous and have bad DX. They offer effectively arbitrary ordering of parameters, and are dangerous to use if there are multiple parameters of the same type(which practically all constructors have). Object initializers exists to fix this issue. In my opinion, constructors for data-models are effectively obsolete.

Constructor-approach:

var body = new EmailMessageV2(
	formMessage.Content,
	formMessage.Subject,
	[..formMessage.ToRecipients.Select(x => new EmailRecipientV2(
		x.EmailAddress
	))],
	null,
	null,
	[..formMessage.CcRecipients.Select(x => new EmailRecipientV2(
		x.EmailAddress
	))],
	null
 );

Object-initializer approach:

var body = new EmailMessageV2
{
	ToRecipients = [..formMessage.ToRecipients.Select(x => new EmailRecipientV2
	{
		EmailAddress = x.EmailAddress,
	})],
	CcRecipients = [..formMessage.CcRecipients.Select(x => new EmailRecipientV2
	{
		EmailAddress = x.EmailAddress,
	})],
	Subject = formMessage.Subject,
	Content = formMessage.Content,
	Attachments = null,
	From = null,
	ActivityLogging = null,
};

The latter here is much clearer and less error-prone. I don't trust the generator to never re-order these parameters. Any re-ordering would be very hard to spot at design-time and would break my code.

Describe the solution you'd like

An option that replaces the constructor-based approach with one where all properties are required and init-only instead.

There are a few possible approaches here:

  1. Create three new config options: makePropertiesRequired (Could be problematic in terms of private setters etc..), makePropertiesInitOnly and generateEmptyConstructor. Adding all three of these would do the trick.

Or you could create one, useObjectInitializerApproach that does all of those things and makes sure it actually works as you'd expect (All properties have public init-only setters, as well as being required).

Maybe nullable properties should not be required, but that should be a separate option entirely imo, as explicitness > implicitness.

Additional context

Should probably require C# 11 and above.

Some people consider required nullable properties to be oxymoronic, but it makes perfect sense to me; You are explicit in the fact that it's null.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the existing C# generator options and the templates or entry points that produce model constructors and properties. The work is complete when a defined configuration generates C# 11-compatible models with required init-only properties, with the intended handling of nullable properties and constructors documented and tested.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.