返回题库高级 .NET 刷题C# 问答题 · 第 2 / 5 篇

C# 问答 02:泛型、集合与 LINQ

021 泛型如何减少装箱并提高类型安全?

难度: 基础

查看参考答案

结论: 类型参数保留具体类型契约,值类型无需先转 object

原因: 编译器可检查成员和转换,运行时也能为值类型实例化合适代码

边界: 接口转换、反射和非泛型 API 仍可能装箱

022 where 约束为什么不仅是文档?

难度: 基础

查看参考答案

结论: 约束决定泛型体内可合法调用的成员并限制类型实参

原因: 它参与编译期类型检查和部分运行时构造验证

边界: notnull 等约束主要影响可空诊断,不自动注入业务校验

023 协变和逆变如何判断方向?

难度: 基础

查看参考答案

结论: 只输出 T 的接口可协变,只输入 T 的接口可逆变

原因: IEnumerable<Dog> 可视为 IEnumerable<Animal>,IComparer<Animal> 可用于比较 Dog

边界: 型变仅适用于引用类型构造,List<T> 本身保持不变

024 IEnumerable<T> 参数意味着什么?

难度: 基础

查看参考答案

结论: 只承诺可枚举,不承诺计数、索引、可重复或无副作用

原因: API 若需多次遍历应物化或提高参数契约

边界: 不要未经确认调用 Count 后再枚举远程或一次性序列

025 IReadOnlyList<T> 是否保证不可变?

难度: 基础

查看参考答案

结论: 不保证,只限制当前引用的写操作

原因: 底层 List 仍可能被其他持有者修改

边界: 需要稳定快照应复制到数组或使用不可变集合

026 List<T> 的容量如何影响性能?

难度: 基础

查看参考答案

结论: 预估 Capacity 可减少扩容和数组复制

原因: 容量不是 Count,过度预留会浪费内存

边界: 只在已知规模和热点数据下设置,不要机械调大

027 Dictionary 键为什么应不可变?

难度: 进阶

查看参考答案

结论: 键入表后若哈希或相等字段改变,所在桶与新哈希不一致

原因: 查询、删除可能再也找不到该键

边界: 可变对象可作为键,但参与相等的状态必须在驻留期稳定

028 如何选择 Dictionary 的字符串比较器?

难度: 进阶

查看参考答案

结论: 协议和标识符常用 Ordinal 或 OrdinalIgnoreCase,用户语言文本按具体文化

原因: 比较器同时影响相等和哈希

边界: 不要依赖当前文化作为跨机器持久标识规则

029 HashSet 适合解决什么问题?

难度: 进阶

查看参考答案

结论: 高频成员测试、去重和集合运算

原因: 平均 O(1) 依赖良好哈希,不提供业务顺序保证

边界: 需要稳定展示顺序时另存顺序或选择有序结构

030 并发集合能否替代所有锁?

难度: 进阶

查看参考答案

结论: 不能,它只保证自身单个或文档声明的复合操作线程安全

原因: 跨多个集合和业务状态的不变量仍需同步

边界: 优先使用 GetOrAdd、AddOrUpdate 等原子 API,注意工厂可能执行多次

031 不可变集合的主要价值是什么?

难度: 进阶

查看参考答案

结论: 修改返回新版本,旧快照可安全共享

原因: 结构共享降低复制但不是零成本

边界: 批量构建用 Builder,极高频只读可考虑 Frozen 集合

032 延迟执行有什么收益和风险?

难度: 进阶

查看参考答案

结论: 可流式组合并避免不需要的工作,但每次枚举会重新执行查询

原因: 源变化、副作用和重复 I/O 会影响结果

边界: 在系统边界明确决定保持流式还是 ToList 快照

033 Any、Count 和 First 应如何选择?

难度: 进阶

查看参考答案

结论: 按语义选最弱操作,只问存在用 Any,只取首项用 First

原因: Count 对无快速计数接口的源可能完整遍历

边界: 不要为了一个元素把整个序列 ToList

034 First 与 Single 的异常语义差异是什么?

难度: 进阶

查看参考答案

结论: First 验证至少一个,Single 还验证不超过一个

原因: Single 能表达数据库唯一性假设但可能额外读取

边界: OrDefault 版本还要处理 default 是合法值的歧义

035 GroupBy 为什么可能占用大量内存?

难度: 实战

查看参考答案

结论: Enumerable.GroupBy 通常先读取完整源并构建分组查找

原因: 高基数或无限流会导致高内存或无法产出

边界: 流式分组需要输入有序并使用专门算法或数据库聚合

036 Join 与 GroupJoin 如何区分?

难度: 实战

查看参考答案

结论: Join 产生内连接平面结果,GroupJoin 为每个外部元素提供匹配组

原因: 左外连接可在 GroupJoin 后 DefaultIfEmpty

边界: 选择取决于结果形状而不只是 SQL 名称

037 如何避免 LINQ 热路径的隐藏分配?

难度: 实战

查看参考答案

结论: 识别闭包、迭代器、接口枚举和物化,使用静态 Lambda 或直接循环验证热点

原因: 可读性通常优先,优化必须有基准

边界: 不要假设所有 LINQ 都慢,也不要无条件重写

038 Span 为什么不能作为普通集合字段?

难度: 实战

查看参考答案

结论: Span 是 ref struct,引用安全不允许逃逸到普通堆对象

原因: 它可能指向栈或可移动内存,生命周期必须静态受控

边界: 长期持有改用 Memory<T> 或明确所有权的数组

039 ArrayPool 使用时要遵守什么所有权?

难度: 实战

查看参考答案

结论: 租借者独占使用有效区间并在最后使用后归还

原因: 返回数组可能更大且含旧数据,敏感内容需清理

边界: 异步操作完成前不能归还,归还后不能继续访问

040 如何为集合 API 表达所有权?

难度: 实战

查看参考答案

结论: 说明调用方能否修改、是否复制、是否缓存和枚举成本

原因: 接口只描述操作面,不能替代生命周期文档

边界: 公共边界可返回快照,内部热点可用租借缓冲并明确释放

官方资料

当前分类

C# 问答题

查看全部分类 →
  1. 01C# 问答 01:语言基础与面向对象20 题
  2. 02C# 问答 02:泛型、集合与 LINQ20 题
  3. 03C# 问答 03:异步、并发与取消20 题
  4. 04C# 问答 04:CLR、GC、内存与性能20 题
  5. 05C# 问答 05:现代 C#、API 设计与代码审查20 题
ESC

输入关键词开始搜索