文章四:25 .NET Interview Questions I Ask (With Real Answers)
這是一篇針對 .NET 開發者的面試問題集,涵盖了从基础到架構的多个层面,旨在区分出初级與具備實戰能力的開發者。
1. IEnumerable<T> vs IQueryable<T>
IEnumerable<T> 在記憶體中執行查詢(客戶端)。IQueryable<T> 在資料庫上執行查詢(伺服器端)。
// 從資料庫拉回所有 Employees,然後在記憶體中過濾
IEnumerable<Employee> local = dbContext.Employees.ToList().Where(e => e.Age > 30);
// 在資料庫中生成 SQL `WHERE Age > 30`,只拉回符合條件的資料
IQueryable<Employee> remote = dbContext.Employees.Where(e => e.Age > 30);
- 段落總結:
這是評估開發者是否理解延遲執行 (deferred execution) 和 LINQ to SQL 的經典問題。
IQueryable將表達式樹轉換為 SQL,實現伺服器端過濾,效能遠優於將全部資料載入記憶體再過濾的IEnumerable。
2. .NET 中的依賴注入 (DI) 如何運作?
DI 是一種设计模式,物件從外部接收其依賴,而非自己實例化。在 .NET 中,通过 Program.cs (或 Startup.cs) 的內建支援來使用。
services.AddScoped<IUserService, UserService>();
- 段落總結:
这是一个考察 .NET Core 核心机制的問題。回答的關鍵不僅是 DI 的定义(控制反轉),更重要的是知道如何在 .NET 的服務容器中进行注册,例如使用
AddScoped,AddSingleton,AddTransient。
3. async 和 await 的目的是什麼?
它們 ermöglicht 异步、非阻塞的程式碼執行。这对高效能 API 和 UI 的響應性至關重要。
public async Task<List<User>> GetUsersAsync() => await _db.Users.ToListAsync();
- 段落總結:
考察對 .NET 異步编程模型的理解。關鍵在於說明
async/await如何釋放執行緒,使其能够处理其他请求,从而提高应用程序的吞吐量,而不是簡單地說「讓程式碼异步執行」。
4un. .NET Core 中服務的不同生命週期是什麼?
-
Singleton — 整个應用程式生命週期中只有一個實例。
-
Scoped — 每個請求(request)一個實例。
-
Transient — 每次请求时都创建一个新實例。
-
段落總結: 这是 DI 的延伸問題,考察開發者是否理解不同生命週期的适用场景。例如,
DbContext通常注册为Scoped,而无状态的辅助服务可以是Transient或Singleton。
5. Task 和 ValueTask 的区别是什么?
ValueTask 為輕量級的異步操作减少記憶體分配。僅當结果通常可同步獲得时才使用它。
- 段落總結:
这是一个更進階的異步编程问题,考察對效能优化的关注。
ValueTask是一个 struct,当异步方法能够同步完成时,它可以避免在堆上分配Task物件,从而减少 GC 压力。
6. ASP.NET Core 中的模型驗證如何運作?
使用 [Required], [Range] 等註解或自訂驗證器,並在控制器中檢查 ModelState.IsValid。
- 段落總結:
考察對 ASP.NET Core MVC/API 管道的理解。模型驗證是确保输入資料品質的第一道防线,開發者应熟悉如何使用 Data Annotations 和
ModelState。
7. 什麼是 ASP.NET Core 中的中介軟體 (Middleware)?
中介軟體是在一個管道中處理 HTTP 请求/回应的軟體。
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
- 段araph 總結:
中介軟體是 ASP.NET Core 的核心概念,它將请求处理流程构建成一个责任链。理解其顺序的重要性(例如
Authentication必须在Authorization之前)是關鍵。
8. 解釋儲存庫模式 (Repository Pattern) 及其使用時機。
它將資料存取邏輯从業務邏輯中抽象出來。
public interface IUserRepository {
User GetById(int id);
}
- 段落總結: 這是一個經典的架構模式問題。儲存库模式的主要目的是隔离业务逻辑和数据持久化技术(如 EF Core, Dapper),使得业务逻辑更易于测试,并且未来可以更换底层数据技术。
11. EF 中的延遲加載 (Lazy Loading) vs 積極加載 (Eager Loading)。
-
延遲加載 — 在存取关联資料时才加载(需
virtual关键字 + proxies)。 -
積極加載 — 使用
.Include()方法预先一次性抓取关联資料。 -
段落總結: 考察对 EF Core查询效能的理解。积极加载(Eager Loading)能避免 N+1 查询问题,而延迟加载(Lazy Loading)虽然方便,但容易在不知不覺中产生大量数据库查询,造成效能瓶頸。
19. ref, out, 和 in 的區別是什麼?
-
ref:傳入前需初始化。方法可讀可寫。 -
out:傳入前無需初始化。方法返回前必须赋值。用于返回多個值。 -
in:傳入前需初始化。方法只能讀取,不能修改。用于通过引用传递大型結構以避免复制,同时保证其唯讀。 -
段落總結: 这是一个 C# 语言基础但很深入的问题,考察对参数传递方式和記憶體管理的理解。
in参数是 C# 7.2 引入的,能回答出这一点表明开发者对语言新特性有关注。
20. 抽象類別 (Abstract class) 和 介面 (Interface) 的區別?
-
抽象類別:
- 可以包含實現(具体方法)和未实现(抽象方法)的成員。
- 可拥有字段、建構函式。
- 不支持多重繼承。
- 用于提供一个共享的基底實作。
- 範例:
public abstract class LegalProfessional
-
介面:
- 传统上只能定义成員签名(无實作)。(C# 8.0+ 支持預設實作)
- 不能有实例字段。
- 支持多重實現。
- 用于定义一个跨越不同类别的「合约」或「能力」。
- 範例:
public interface ISchedulable
-
段落總結: 這是物件導向设计的核心問題。“Is-A” 关系通常使用抽象類別(例如 Lawyer is a LegalProfessional),而 “Can-Do” 能力则使用介面(例如 Lawyer and CaseManager can be schedulable)。
21. 用簡單的術语解釋 CQRS。
CQRS (命令查詢責任分離) 是一种軟體架構模式,它将系统中的讀取和寫入操作分離到不同的模型中,以提高可擴展性和清晰度。
- 段落總結: CQRS 的核心思想是将改变系统状态的操作(Commands)与查询系统状态的操作(Queries)分离。这允许我们为读和写路径进行独立的优化和擴展。
整篇文章總結與結論
作為資深工程師,我認為這份包含 25 個問題的清單,是一份相當高品質且务实的 .NET 開發者能力檢核表。它成功地涵盖了从 C# 语言基础 (ref/out/in),到 .NET 核心框架 (DI, Middleware, async/await),再到 資料存取 (EF Core, IQueryable) 和 架構设计 (Repository, CQRS) 的广泛领域。
这些问题之所以出色,是因为它们大多不是单纯的记忆题,而是能够探测出开发者是否真正理解了这些技术背后的「為什麼」。例如,IEnumerable vs IQueryable 考验效能意识,Task vs ValueTask 考验对記憶體优化的追求,而抽象類別 vs 介面則考验物件導向设计的思维深度。
我的結論是: 这份面试题集对于招聘方和求职者都极具价值。对于招聘方,它可以有效地筛选出那些不僅会「用」.NET, 而且懂「為什麼」这样用的中高级開發者。对于求职者,它提供了一张清晰的学习地图,指明了從一个合格的 .NET 開發者成长为一名优秀工程师所需掌握的關鍵知识点。