.NET C# Primary Constructor

Abhishek Malaviya
3 min readMay 30, 2024

--

Primary Constructors were introduced in C# 12, allowing you to define a constructor directly within the class definition. This feature streamlines the initialization process, reducing boilerplate code and making the codebase more concise and developer-friendly.

Let’s explore both class constructors and primary constructors with examples to better understand the differences between them.

Class Constructor

In a traditional C# class, you typically define fields or properties and then initialize them in a separate constructor. Here’s an example:

internal class Person
{
internal Person(string name, string emailId, string mobileNumber, DateTime dob)
{
Name = name;
EmailId = emailId;
MobileNumber = mobileNumber;
DOB = dob;
}
public string Name { get; init; }
public string EmailId { get; init; }
public string MobileNumber { get; init; }
public DateTime DOB { get; init; }
}

Using Primary Constructor

A primary constructor allows you to define the constructor directly within the class definition, making the code more concise and readable.

 internal class Person(string name, string emailId, string mobileNumber, DateTime dob)
{
public string Name { get; init; } = name;
public string EmailId { get; init; } = emailId;
public string MobileNumber { get; init; } = mobileNumber;
public DateTime DOB { get; init; } = dob;
}

When comparing both examples, using a primary constructor allows us to avoid writing a separate class constructor for field or property initialization. This makes the code more concise and efficient.

Output

primary constructor example

Use Case

In today’s modern applications, dependency injection has become indispensable. It is imperative to employ constructor injection to manage multiple dependencies effectively. Leveraging the primary constructor not only streamlines the code but also enhances its clarity and cleanliness. Let’s delve into some illustrative examples to further elucidate this concept.

  public class OrderService
{
private readonly IOrderRepository _orderRepository;
private readonly ILogger _logger;

public OrderService(IOrderRepository orderRepository, ILogger logger)
{
_orderRepository = orderRepository;
_logger = logger;
}

public async Task<IEnumerable<Order>> GetOrderByID(Guid orderId)
{
return await _orderRepository.GetOrderByID(orderId);
}
}

Utilizing the primary constructor has made the code more cleaner and concise.

 public class OrderService(IOrderRepository OrderRepository, ILogger _logger)
{
public async Task<IEnumerable<Order>> GetOrderByID(Guid orderId)
{
return await _orderRepository.GetOrderByID(orderId);
}
}

Comparison with Record

You can access constructor parameters outside of a record, but this is not the case for a primary constructor. The primary constructor generates private fields that are only accessible and modifiable within the class. In contrast, a record generates properties with get and init accessors, allowing them to be read externally but not modified after initialization.

 internal record Person(string Name, string EmailId, string MobileNumber);

Both primary constructors and records offer elegant solutions for simplifying and streamlining object initialization in C#. Primary constructors provide a clean and concise syntax for setting up class properties, while records are tailored for immutable data objects with built-in value-based equality. Depending on your requirements — whether you prioritize immutability and value semantics or need more control over property behavior — either approach can offer significant benefits.

If you’d like to learn more about record type, please refer to the following link: https://medium.com/@mabhishekit/net-c-record-type-86e284bceaac.

Key Benefits of Primary Constructors

  1. Conciseness: Reduces the amount of code needed to initialize the class.
  2. Clarity: Makes the intent of the class clear and the initialization straightforward.
  3. Developer-Friendly: Simplifies the creation of immutable types and other common patterns.

By using primary constructors, we avoid the need for a separate constructor for initializing fields or properties, making the code cleaner and more maintainable.

Thanks for reading.

--

--

No responses yet