Primary constructors has caused concerns for C# developers

Published: Tuesday 28 November 2023

Primary constructors is one of the new exciting features for C# 12.

However, there have been concerns from developers about whether to use them.

We'll review what the problem is, and whether we should be using them right now.

Dependency injection usage

When using dependency injection in .NET, the common approach is to inject the service into a constructor's parameter, and store the instance as a private readonly field.

public class AbcController : Controller
{
	private readonly IAbcService _abcService;
	
	public AbcController(IAbcService abcService) {
		_abcService = abcService;
	}
}

With primary constructors, we don't need to add the constructor as we can add the instance as a class parameter and we can use the instance throughout the class.

public class AbcController(IAbcService abcService) : ControllerBase
{
}

So this is the same but with less code, isn't it?

Not exactly. As parameters are mutable, we lose the read-only part of the instance when using it with primary constructors.

Why is it a problem to lose the read-only part?

The instance can be changed through any part of the class as is demonstrated with this code snippet:

public class AbcController(IServiceProvider serviceProvider, IAbcService abcService)
	: ControllerBase
{
	[HttpGet]
	public IActionResult MyMethod()
	{
		var number = abcService.MyNumber();

		abcService = null;
		var number2 = MyAbc();

		return Ok(number);            
	}

	public int MyAbc()
	{
		return abcService.MyNumber();
	}
}

In this instance, the MyMethod method would throw a NullReferenceException.

The reason being is that we set the abcService parameter to null and then call the MyAbc method which calls the MyNumber method from the abcService parameter.

As there would be null reference to the abcService parameter at that stage, it would throw an exception.

As a result, it increases the chances of runtime exceptions being thrown.

When we will see read-only parameters?

At the .NET conference, we asked that very question:

X (formerly Twitter) post asking about making primary constructors readonly

X (formerly Twitter) post asking about making primary constructors readonly

Mads Torgersen, lead designer of the C# language and Dustin Campbell, principal software engineer at Microsoft answered our question at the .NET conference. Watch their response here.

They stated that they are aware of the request to add read-only primary constructor parameters.

However, they stated that they're questions around how much should you be able to put on a parameter. Read-only makes sense, but should you be able to add an access modifier on a parameter?

They go on to say that they talked at length multiple times in language designed meetings but decided to defer it to a later date.

Although they aren't committed to it being in the language, they are at least committed to looking at it.

Should we be using primary constructors for dependency injection at this stage?

Using primary constructors with dependency injection works great and reduces code bloat as we don't have to have to include a constructor to inject a service.

However, as parameters are mutable, there is a risk that the instance could get changed in another part of the class.

It's down to the developer whether they want to take that risk or not.

Watch our video to understand in more detail about the problem with using primary constructors for dependency injection: