C# 问答 05:现代 C#、API 设计与代码审查
081 如何选择 Task 和 ValueTask?
难度: 基础
查看参考答案
结论: 默认使用 Task,只有高频同步完成且分配被证明是瓶颈时考虑 ValueTask
原因: ValueTask 更大且消费规则复杂
边界: 公开 API 改返回类型是契约变更,应用基准和调用模式决定
082 required 与构造函数如何配合?
难度: 基础
查看参考答案
结论: 核心不变量优先构造函数,required 适合对象初始化器必须提供的成员
原因: SetsRequiredMembers 只是承诺,编译器不验证实现
边界: 外部输入仍需运行时验证
083 C# 14 field 关键字解决什么?
难度: 基础
查看参考答案
结论: 让属性访问器使用编译器后备字段并加入校验逻辑
原因: 已有 field 标识符可能出现含义变化
边界: 它不暴露字段给外部,也不适用于任意方法
084 扩展成员的设计边界是什么?
难度: 基础
查看参考答案
结论: 为不能修改的类型提供发现友好的辅助 API
原因: 静态绑定且不能访问目标私有状态
边界: 核心领域行为更适合实例成员或独立服务
085 空条件赋值何时有价值?
难度: 基础
查看参考答案
结论: 接收者可选且缺失时应跳过赋值的场景
原因: 右侧在接收者为 null 时不会求值,需确认副作用符合预期
边界: 它不能替代需要报告缺失对象的验证
086 如何设计取消参数?
难度: 基础
查看参考答案
结论: 异步可取消 API 通常把 CancellationToken 放在末尾并传到底层
原因: 可选令牌不代表实现可忽略取消
边界: 开始不可回滚提交后要定义取消是否仍被接受
087 公共 API 的异常契约应写什么?
难度: 进阶
查看参考答案
结论: 参数错误、状态错误、外部失败和取消的异常类型及条件
原因: 不要泄漏可随实现变化的内部异常
边界: 包装异常时保留 InnerException 和可诊断上下文
088 集合返回值怎样兼顾性能与封装?
难度: 进阶
查看参考答案
结论: 按所有权返回只读视图、不可变快照或明确租借缓冲
原因: IReadOnlyList 不自动复制
边界: 高频路径可提供 Span 回调等受控 API,但不能让引用逃逸
089 如何设计 Try 模式?
难度: 进阶
查看参考答案
结论: 可预期失败返回 bool,成功值通过 out 提供
原因: 失败 out 值不应承载业务意义
边界: 不可恢复系统错误仍应抛异常,不能全部转 false
090 什么时候用泛型静态抽象成员?
难度: 进阶
查看参考答案
结论: 数值和工厂类算法需对类型级操作静态分派时
原因: 约束会增加 API 学习和实现成本
边界: 简单策略注入仍可能更适合普通接口实例
091 源生成适合解决哪些问题?
难度: 进阶
查看参考答案
结论: 把可预测的运行时反射或模板工作移到编译期
原因: 生成器必须增量、确定并报告诊断
边界: 它不适合依赖运行时未知类型的全部场景
092 分析器规则如何落地?
难度: 进阶
查看参考答案
结论: 先建立基线,按严重度逐步启用并提供可执行修复
原因: 一次把所有警告升错误会阻塞无关交付
边界: 规则应版本化并在 CI 与本地一致
093 如何审查 null 契约?
难度: 进阶
查看参考答案
结论: 检查输入、输出、成员状态和条件式注解是否与实现一致
原因: ! 只消除警告,不修复运行时问题
边界: 边界处验证,内部通过不变量减少重复检查
094 如何审查异步 API?
难度: 进阶
查看参考答案
结论: 检查是否真正异步、是否传取消、异常如何传播以及是否隐藏并发
原因: 同步完成路径也要正确
边界: 不使用 async 关键字不代表方法不是异步 API
095 如何审查线程安全声明?
难度: 实战
查看参考答案
结论: 明确保护的状态、同步原语、锁顺序和回调边界
原因: 线程安全集合不保证跨操作业务原子性
边界: 文档应说明实例级还是静态级安全
096 如何避免破坏二进制兼容?
难度: 实战
查看参考答案
结论: 区分源码、二进制和行为兼容,谨慎修改虚成员、默认参数和接口
原因: 默认接口实现只能缓解部分接口演进
边界: 发布前用 API 比较工具和旧调用方测试
097 如何设计日志 API 调用?
难度: 实战
查看参考答案
结论: 使用结构化模板并延迟昂贵参数计算
原因: 高频禁用日志可用 LoggerMessage 源生成或插值处理器
边界: 不要提前拼接字符串,也不要记录敏感数据
098 代码审查中如何判断一项性能优化?
难度: 实战
查看参考答案
结论: 要求剖析证据、基准、可读性成本和回退方案
原因: 局部微基准必须验证端到端收益
边界: 没有数据的复杂低级代码不应仅凭经验合并
099 如何处理版本相关语言特性?
难度: 实战
查看参考答案
结论: 记录目标 TFM、LangVersion 和部署运行时基线
原因: C# 14 官方支持 .NET 10,超前语言版本组合不受支持
边界: 库面向旧 TFM 时还需验证引用程序集和消费者编译器
100 一个高质量 API 评审清单包含什么?
难度: 实战
查看参考答案
结论: 命名、空值、异常、取消、所有权、并发、性能、可测试性和演进
原因: 清单用于发现风险而非代替领域判断
边界: 结论应给具体场景、边界和验证方式