Back to results for “Dependency injection”
.NET › Dependency Injection

What is dependency injection, and why does it make a codebase easier to test and maintain?

Intermediate

Answer

Dependency injection (DI) is a design pattern where a class receives the dependencies it needs from outside (typically via its constructor) rather than creating them itself -- this loosens coupling (a class depends on an interface, not a concrete implementation), makes unit testing far easier (a test can inject a mock/fake implementation instead of the real dependency), and centralizes how dependencies are wired together, so swapping an implementation later doesn't require touching every class that uses it.
// Tightly coupled: OrderService creates its own dependency directly
public class OrderService {
    private PaymentService _paymentService = new(); // hardcoded, hard to test or swap
}

// Loosely coupled via constructor injection
public class OrderService {
    private readonly IPaymentService _paymentService;
    public OrderService(IPaymentService paymentService) => _paymentService = paymentService;
}

// ASP.NET Core registers the mapping once, centrally
builder.Services.AddScoped<IPaymentService, PaymentService>();
Real-world example A team writing unit tests for OrderService injects a fake IPaymentService that always returns success, testing OrderService's own logic in complete isolation without needing a real payment gateway connection during every test run.

Common follow-ups: What's the difference between constructor, property, and method injection?;How does ASP.NET Core's built-in DI container decide an object's lifetime (transient, scoped, singleton)?