0
0
CsharpComparisonBeginner · 4 min read

Constructor Injection vs Property Injection in C#: Key Differences and Usage

In C#, constructor injection passes dependencies through a class constructor, ensuring they are set when the object is created. Property injection sets dependencies via public properties after object creation, allowing optional or changeable dependencies.
⚖️

Quick Comparison

This table summarizes the main differences between constructor injection and property injection in C#.

FactorConstructor InjectionProperty Injection
Dependency Setup TimeAt object creation via constructorAfter object creation via property setter
Mandatory DependenciesEnforced by constructor parametersNot enforced, can be optional
ImmutabilityDependencies are readonly after constructionDependencies can be changed anytime
TestabilityEasier to test with guaranteed dependenciesMay require extra setup to ensure dependencies are set
Use CaseRequired dependencies that must existOptional or changeable dependencies
Code ClarityClear contract of required dependenciesLess explicit, can lead to missing dependencies
⚖️

Key Differences

Constructor injection requires all necessary dependencies to be provided when creating an object. This makes the dependencies explicit and guarantees they are available, which helps avoid runtime errors. It also supports immutability because dependencies are set once and cannot be changed later.

In contrast, property injection allows dependencies to be set or changed after the object is created through public properties. This flexibility is useful when dependencies are optional or need to be replaced during the object's lifetime. However, it can lead to errors if dependencies are not set before use, making the code less safe.

Constructor injection promotes clearer and safer code by enforcing dependency requirements upfront, while property injection offers more flexibility but requires careful handling to avoid missing dependencies.

⚖️

Code Comparison

Here is an example of constructor injection where the dependency is passed through the constructor and stored in a readonly field.

csharp
public interface IMessageService
{
    void Send(string message);
}

public class EmailService : IMessageService
{
    public void Send(string message)
    {
        System.Console.WriteLine($"Email sent: {message}");
    }
}

public class Notification
{
    private readonly IMessageService _messageService;

    public Notification(IMessageService messageService)
    {
        _messageService = messageService;
    }

    public void Alert(string message)
    {
        _messageService.Send(message);
    }
}

// Usage
var emailService = new EmailService();
var notification = new Notification(emailService);
notification.Alert("Hello via constructor injection!");
Output
Email sent: Hello via constructor injection!
↔️

Property Injection Equivalent

This example shows property injection where the dependency is set via a public property after object creation.

csharp
public interface IMessageService
{
    void Send(string message);
}

public class EmailService : IMessageService
{
    public void Send(string message)
    {
        System.Console.WriteLine($"Email sent: {message}");
    }
}

public class Notification
{
    public IMessageService MessageService { get; set; }

    public void Alert(string message)
    {
        if (MessageService == null)
        {
            throw new System.InvalidOperationException("MessageService dependency not set.");
        }
        MessageService.Send(message);
    }
}

// Usage
var emailService = new EmailService();
var notification = new Notification();
notification.MessageService = emailService;
notification.Alert("Hello via property injection!");
Output
Email sent: Hello via property injection!
🎯

When to Use Which

Choose constructor injection when dependencies are required for the class to function correctly and should not change after creation. This ensures safety, clarity, and immutability.

Choose property injection when dependencies are optional, may change during the object's lifetime, or when you need to avoid complex constructors. Use it carefully to avoid missing dependencies at runtime.

Key Takeaways

Constructor injection enforces required dependencies at object creation for safer, clearer code.
Property injection allows optional or changeable dependencies but requires careful handling.
Use constructor injection for mandatory dependencies and property injection for optional ones.
Constructor injection supports immutability; property injection supports flexibility.
Always check for null dependencies when using property injection to avoid runtime errors.