绝大多数情况下无需手写Adapter类,C#的隐式转换、委托、扩展方法或record映射更轻量安全;仅当桥接不可修改的第三方类型(如IDataReader与IAsyncEnumerable)或封装sealed遗留类(如LegacyPaymentService)时才需正式Adapter。

绝大多数情况下,你不需要手写完整的 Adapter 类——C# 提供的隐式转换、委托、扩展方法或 record 映射,比硬套适配器模式更轻、更安全、更易调试。
什么时候真该写 Adapter 类
只有两类场景值得上正式的适配器:
- 你要桥接不可修改的第三方类型,比如老版
IDataReader和新版IAsyncEnumerable<t></t>,且它们之间没有共用抽象 - 你要封装一个密封类(
sealed),比如LegacyPaymentService,而它又不实现你期望的接口(如IPaymentProcessor)
其他情况,比如两个类字段名一致、行为相似,直接用 record 构造或属性赋值就够了;强行套 Adapter 只会让调用链变成 A → B → C → D,堆栈里全是 Adapter,查错时根本分不清哪一层在丢数据。
对象适配器怎么写才不踩坑
这是最常用也最推荐的方式,靠组合而非继承,兼容性好,但容易漏掉生命周期管理:
- 构造函数必须接收被适配对象(
Adaptee),别用new Adaptee()内联创建——否则无法控制其生命周期 - 如果
Adaptee实现了IDisposable,你的Adapter也得实现,并在Dispose()里转发调用,否则资源泄漏 - 不要给未实现的方法留空体,比如
BeginScope这种 ILogger 成员,显式 throwNotSupportedException,避免调用方误以为“能用” - 别在
Adapter里做耗时转换(比如 JSON ↔ XML 全量解析),这种逻辑应该前置或缓存,否则每次Request()都卡住主线程
类适配器为什么基本不用
C# 不支持多继承,所以所谓“类适配器”只能是「继承一个具体类 + 实现一个接口」,限制极多:
-
Adaptee必须是非sealed类,否则编译直接报错 - 你无法再继承别的基类,一旦项目后续引入需要共同基类的组件(比如所有日志器都要继承
BaseLogger),这条路就彻底堵死 - 调试时堆栈显示的是
ClassAdapter.SpecificRequest(),但实际执行的是父类方法,容易误判问题归属 - 若
Adaptee后续升级加了新虚方法,你这个子类不会自动继承行为变更,维护成本陡增
比 Adapter 更轻的替代方案有哪些
很多所谓“接口不兼容”,其实根本不需要新建类:
- 有
implicit operator?直接定义转换,编译器自动触发,零开销,无额外类型 - 只是字段映射?用
record或AutoMapper的CreateMap<a b>()</a>,比写Adapter少 10 行代码、少 3 层调用 - 只差一两个方法?加个
static class扩展方法,比如给DataTable加ToAsyncEnumerable(),干净利落 - 目标接口是 Func/Action?直接传
x => adaptee.Do(x),连类都不用建
真正难的不是怎么写 Adapter,而是判断“到底需不需要写”——多数时候,那个“不兼容”只是你没看清底层契约,或者过早设计了抽象。


















