What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
In .NET dependency injection, registering a concrete class is valid; the testing trade-off depends on what the consumer requests. If a constructor asks for the concrete type, that implementation is part of the consumer’s API. If it asks for an interface, the container can supply the usual implementation while tests or other configurations can substitute another one. That seam is valuable when substitution solves a real problem—not because every class needs an interface.
What the registration line does—and does not—decide
Dependency injection separates object construction and wiring from the classes that consume dependencies. An abstraction lets a consumer name a contract while the container supplies a concrete implementation. In ASP.NET Core, both concrete-only and interface-backed registrations are supported.
builder.Services.AddScoped<IMyDependency, MyDependency>();
Here, IMyDependency is the service type consumers can request, and MyDependency is its implementation. A concrete-only registration can look like this:
builder.Services.AddSingleton<MyDependency>();
Microsoft documents implementation-type-only registration as equivalent to registering the same type as both service type and implementation type. These examples also use different lifetimes—scoped and singleton—so they do not isolate the effect of using an interface. To compare only the service type, keep lifetime and other configuration choices the same. See Microsoft’s ASP.NET Core dependency-injection guidance.
Why the constructor matters more for substitution
Consider a consumer that requests MyDependency in its constructor: its declared dependency is the concrete implementation. A test or alternate runtime configuration cannot satisfy that constructor with a different implementation unless it is compatible with that concrete type. If the constructor requests IMyDependency, a different implementation of that contract can be supplied instead.
This matters most when the real dependency has external effects, is slow or costly to use, or makes the unit under test difficult to isolate. A substitute can help test the consumer without invoking those behaviors. Microsoft’s ASP.NET Core documentation puts the general point this way: “Requesting dependencies as constructor parameters yields classes that are easier to test.” The benefit comes from making dependencies explicit and providing a useful substitution seam—not from an interface being inherently easier to test.
The registration line alone does not determine testability. A concrete dependency may be easy to exercise as-is; an interface does not automatically make a test isolated or useful. Inspect both the constructor and what the dependency does.
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Concrete class or interface: how to choose
| Decision factor | Concrete dependency | Interface-backed dependency |
|---|---|---|
| What the consumer names | The concrete class, such as MyDependency. |
The contract, such as IMyDependency. |
| Substitution | Useful when consumers should rely on this implementation and no practical alternative is needed. | Useful when tests or runtime configuration need another implementation that satisfies the contract. |
| Multiple meaningful implementations | Can be sufficient when there is one intended, stable dependency. | Can make sense when callers need to remain independent of implementation details or more than one implementation is meaningful. |
| Design overhead | Avoids an interface that adds no useful boundary. | Adds an abstraction to maintain; it should express a real caller need rather than satisfy a blanket rule. |
| ASP.NET Core registration | AddSingleton<MyDependency>() registers the type as its own service, with singleton lifetime in this example. |
AddScoped<IMyDependency, MyDependency>() registers the interface with the implementation, with scoped lifetime in this example. |
Prefer an interface when it protects callers from implementation details, enables a practical substitute, or represents alternatives that the application genuinely needs. Prefer concrete injection when the class itself is the intended stable dependency and exposing a contract would not create a useful seam. Microsoft’s unit-testing guidance also cautions against indiscriminately passing interface implementations; context matters.
Do not confuse registration with constructing dependencies directly
Choosing a concrete class in a container registration is not the same as a service creating its own dependent objects. Microsoft recommends avoiding direct instantiation of dependent classes inside services because it couples the code to a particular implementation. With dependency injection, a container can still construct and provide a concrete class; the separate design question is whether the consumer should request that class or a contract.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.What is established about testing cost
Official guidance supports the design rationale for constructor injection, abstraction, and substitution, but it does not quantify how much more effort concrete-class registration causes. There is no percentage or universal cost established here: the impact depends on the dependency, the consumer, and whether a realistic substitute is needed.
Rank #4
The registration examples and lifetime semantics above are specific to .NET and ASP.NET Core; the broader decision—what dependency callers declare and whether a substitution boundary is useful—applies beyond that framework. For .NET details, see Microsoft’s dependency-injection overview.
Free tools Windows power users keep installed
One-click scans. No signup required.
Quick Recap
Best Value
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

