DEV Community

mohamed Tayel
mohamed Tayel

Posted on β€’ Edited on

6

Pros and Cons of Primary Constructors in C# 12

Meta Description

Discover how Primary Constructors in C# 12 simplify class definitions by reducing boilerplate and enhancing readability. Learn the differences between traditional constructors and Primary Constructors with clear examples, benefits, limitations, and full code demonstrations.

With the introduction of C# 12, developers gain access to new features designed to simplify class initialization. Primary Constructors allow properties to be declared and initialized directly in the class header, removing the need for explicit fields and constructor methods.

This article covers:

βœ… Best use cases for Primary Constructors.

❌ Scenarios where Primary Constructors should be avoided.

πŸ“Œ Full code examples for both ideal and avoidable scenarios.


πŸš€ Understanding Primary Constructors

Primary Constructors allow parameters to be declared in the class header, automatically treating them as readonly properties.

Example: Traditional Constructor vs. Primary Constructor

Using a Traditional Constructor

public class CustomerBefore
{
    private string _name;
    private int _age;

    public CustomerBefore(string name, int age)
    {
        _name = name;
        _age = age;
    }

    public string GetCustomerInfo()
    {
        return $"Customer: {_name}, Age: {_age}";
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Explicit fields (_name, _age) must be defined.
  • The constructor manually assigns values.
  • Requires additional getter methods for external access.

Using a Primary Constructor (C# 12)

public class CustomerAfter(string Name, int Age)
{
    public string GetCustomerInfo()
    {
        return $"Customer: {Name}, Age: {Age}";
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Name and Age are implicitly readonly properties.
  • No explicit fields or constructor logic is required.
  • More concise and readable.

Usage Comparison

CustomerAfter customer = new CustomerAfter("Mohamed", 30);
Console.WriteLine(customer.GetCustomerInfo());

CustomerBefore oldCustomer = new CustomerBefore("Ahmed", 40);
Console.WriteLine(oldCustomer.GetCustomerInfo());
Enter fullscreen mode Exit fullscreen mode

βœ… When to Use Primary Constructors (Ideal Use Cases)

1️⃣ Simple Data-Holder Classes

Primary Constructors are perfect for small immutable objects that only store data.

public class Coordinate(double Latitude, double Longitude)
{
    public string GetLocation() => $"Lat: {Latitude}, Long: {Longitude}";
}

// Usage
var location = new Coordinate(40.7128, -74.0060);
Console.WriteLine(location.GetLocation());
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Minimal code for storing values.
  • Immutable by default β†’ prevents accidental changes.

2️⃣ Immutable Configuration Models

Primary Constructors work well for immutable application settings.

public class AppConfig(string DatabaseUrl, int MaxConnections)
{
    public void DisplayConfig() => 
        Console.WriteLine($"DB: {DatabaseUrl}, Max Connections: {MaxConnections}");
}

// Usage
var config = new AppConfig("https://mydb.com", 100);
config.DisplayConfig();
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Encourages immutability β†’ values cannot be modified after initialization.
  • Ideal for configuration models that remain unchanged.

3️⃣ DTOs (Data Transfer Objects)

DTOs transfer data between layers but do not contain business logic.

public class UserDto(string Name, string Email)
{
    public void PrintDetails() => Console.WriteLine($"User: {Name}, Email: {Email}");
}

// Usage
var user = new UserDto("Mohamed", "mohamed@example.com");
user.PrintDetails();
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Lightweight & immutable β†’ ensures data consistency.
  • No unnecessary logic inside DTOs.

4️⃣ Lightweight Classes with Minimal Properties

For classes with only a few properties, Primary Constructors simplify the structure.

public class Product(string Name, decimal Price)
{
    public string GetInfo() => $"Product: {Name}, Price: {Price:C}";
}

// Usage
var product = new Product("Laptop", 1500.99m);
Console.WriteLine(product.GetInfo());
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Short, clean, and efficient representation of data.

❌ When to Avoid Primary Constructors (Limitations & Fixes)

1️⃣ Classes Requiring Custom Property Logic

Primary Constructors cannot include property validation or computed values.

❌ Incorrect Approach (Fails Compilation)

public class User(string Name, int Age)
{
    if (Age < 0) throw new ArgumentException("Age cannot be negative"); // ❌ Not allowed in Primary Constructor
}
Enter fullscreen mode Exit fullscreen mode

βœ… Correct Approach (Using Traditional Constructor)

public class User
{
    public string Name { get; }
    public int Age { get; }

    public User(string name, int age)
    {
        if (age < 0) throw new ArgumentException("Age cannot be negative");
        Name = name;
        Age = age;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Primary Constructors lack validation logic.
  • Traditional constructors allow data validation before assignment.

2️⃣ Mutable Objects (Requires Property Modification)

Primary Constructor properties are readonly, making them unsuitable for objects that require modifications.

❌ Incorrect Approach

public class BankAccount(string AccountNumber, decimal Balance)
{
    public void Deposit(decimal amount) => Balance += amount; // ❌ Read-only, cannot modify
}
Enter fullscreen mode Exit fullscreen mode

βœ… Correct Approach (Using Setter)

public class BankAccount
{
    public string AccountNumber { get; }
    public decimal Balance { get; private set; }

    public BankAccount(string accountNumber, decimal balance)
    {
        AccountNumber = accountNumber;
        Balance = balance;
    }

    public void Deposit(decimal amount)
    {
        Balance += amount;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Primary Constructor properties cannot be modified.
  • Explicit setter allows controlled modifications.

3️⃣ Inheritance-Based Designs (Primary Constructors Don't Support Inheritance)

Primary Constructors do not support base class initialization.

❌ Incorrect Approach

public class Animal(string Name) { }
public class Dog(string Name, string Breed) : Animal(Name) { } // ❌ Not Allowed
Enter fullscreen mode Exit fullscreen mode

βœ… Correct Approach (Using Base Constructor)

public class Animal
{
    public string Name { get; }

    public Animal(string name)
    {
        Name = name;
    }
}

public class Dog : Animal
{
    public string Breed { get; }

    public Dog(string name, string breed) : base(name)
    {
        Breed = breed;
    }
}
Enter fullscreen mode Exit fullscreen mode

βœ”οΈ Why?

  • Primary Constructors do not support base class constructor calls.
  • Use a traditional constructor to inherit parameters.

🎯 Final Thoughts

βœ… Use Primary Constructors for:

βœ”οΈ Simple data-holder classes.

βœ”οΈ Immutable settings/configuration models.

βœ”οΈ DTOs and lightweight objects.

❌ Avoid Primary Constructors when:

❌ You need property validation.

❌ The class requires property modification.

❌ The class inherits from another class.

By understanding when and how to use Primary Constructors, you can write **cleaner, more maintainable C# code. πŸš€**

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Top comments (1)

Collapse
 
moh_moh701 profile image
mohamed Tayel β€’ β€’ Edited

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❀️