C# 12 is introducing a concept called primary constructors. This will allow developers to define constructor parameters alongside the class definition, and have them in scope for the entire class.
I'm not sure how I feel about this feature, but it exists so we may as well get used to it. There's one issue with the concept that concerns me, though: How to format class definitions that use primary constructors. Nick Chapsas touches on the issue in his video here. I'd recommend watching the video - Nick introduces an example CachedWeatherHandler class using primary constructors, and asks for community feedback on five different ways the code could be formatted. I've reproduced his five options below:
Option A
public class CachedWeatherHandler(IMemoryCache cache, ILogger<CachedWeatherHandler> logger) : DelegatingHandler
{
// ...
}
Option B
public class CachedWeatherHandler(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger) : DelegatingHandler
{
// ...
}
Option C
public class CachedWeatherHandler(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger
) : DelegatingHandler
{
// ...
}
Option D
public class CachedWeatherHandler(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger)
: DelegatingHandler
{
// ...
}
Option E
public class CachedWeatherHandler(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger) :
DelegatingHandler
{
// ...
}
Community feedback on Nick's video seems to be leaning towards Option C or Option D.
However, I would suggest that the community embrace a slightly different option. Building on Option C, but with slightly different placement of the parenthesis.
The best option (according to Matt)
public class CachedWeatherHandler(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger
) : DelegatingHandler
{
// ...
}
public class CachedWeatherHandlerWithMultipleInterfaces(
IMemoryCache cache,
ILogger<CachedWeatherHandler> logger
) : DelegatingHandler,
InterfaceOne,
InterfaceTwo
{
// ...
}
The advantage of this option is that it is a bit more clear on the delineation between the constructor parameters and the list of implemented classes and interfaces. A few commentors on Nick's YouTube video made (or endorsed) similar suggestions. Shoutout to @vorontsovru270895, @marikselazemaj3428, and @MarcSelman - great minds think alike.