c# 为什么需要接口

7次阅读

接口解决依赖倒置与多态扩展问题,通过最小契约约定“能做什么”而非“怎么做”,支持不同实现类被同一逻辑无缝替换、单元测试模拟及依赖注入,但应避免滥用导致接口爆炸或暴露内部细节。

c# 为什么需要接口

接口解决的是“依赖倒置”和“多态扩展”问题

不是为了写起来更“规范”,而是当多个类需要被同一套逻辑调用,又不能共享实现时,接口提供了最小契约——只约定“能做什么”,不约束“怎么做”。比如 IRepositorySqlRepositoryInMemoryRepository 都能被 OrderService 无缝替换,而不用改服务层代码。

没有接口时,你只能靠基类或具体类型硬 编码

一旦用 class SqlRepository : RepositoryBase,后续加 MongoRepository 就得让它也继承 RepositoryBase,但两者底层差异大,强行共用父类会迅速膨胀出一堆空实现或 throw new NotSupportedException()。接口则允许完全无关的类实现同一组方法:SqlRepositoryMongoRepositoryFakeRepository 可以各自独立,只共享 GetAsyncSaveAsync 等签名。

接口让单元测试和依赖注入真正可行

MoqNSubstitute 只能模拟接口(或抽象类),不能 mock 具体类。如果你的构造函数参数是 SqlRepository,就无法在测试中替换成假实现;但改成 IRepository 后,测试可直接传入 mock 对象。同样,IServiceCollection.AddScoped, SqlRepository>() 这类注册才成立——DI 容器靠接口类型解析实现,不是靠类名。

接口不是越多越好,滥用会导致“接口爆炸”

一个类暴露 5 个接口(IReadableIWritableISearchable……)看似灵活,实际让调用方不断 asis 判断,违背了单一职责。更常见的问题是:把本该是内部细节的方法(如 ResetConnection()FlushCache())放进公共接口,导致所有实现都必须处理它,哪怕根本不适用。接口应只包含调用方真正需要的、稳定的行为契约。

public interface ICalculator {double Add(double a, double b);     double Multiply(double a, double b); }  // 调用方只依赖这个契约,不关心是内存计算还是调远程 API public class Service {private readonly ICalculator _calc;     public Service(ICalculator calc) => _calc = calc;      public double TotalPrice(double price, double taxRate) =>         _calc.Add(price, _calc.Multiply(price, taxRate)); }

接口真正的复杂点不在定义,而在识别“谁是调用方、谁是实现方、契约边界在哪”。很多团队过早抽象,结果接口刚写完就被三个不同业务需求撕成两半——这时候删掉接口,比硬撑着维护更诚实。

星耀云
版权声明:本站原创文章,由 星耀云 2026-01-05发表,共计1296字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources