Joseph Chen
在鴻海的 TMS 專案裡用過 ASP.NET,第一次看到 LINQ 的時候以為在看 SQL,後來才發現它是 C# 的內建語言整合查詢——比 Python 的 list comprehension 還強大。
C# 特色
C# 是 Microsoft 開發的強型別物件導向語言,2002 年隨 .NET Framework 發布。現在的 .NET Core / .NET 5+ 已跨平台支援 Windows/Linux/macOS,在企業後端開發是主流選項之一。
| 特性 | C# | Java(對照) | Python(對照) |
|---|---|---|---|
| 型別系統 | 強型別 + 型別推斷 (var) | 強型別 | 動態型別 |
| 記憶體管理 | 垃圾回收(GC) | 垃圾回收(GC) | 垃圾回收(GC) |
| async/await | 一等公民,語言原生支援 | 需要第三方框架 | 原生支援(asyncio) |
| LINQ | 內建語言整合查詢 | 需要 Stream API | 無直接對應 |
| 跨平台 | .NET Core / .NET 5+ | 原生跨平台(JVM) | 原生跨平台 |
| 主要用途 | Web API、企業系統、遊戲(Unity) | Web、Android、企業 | 腳本、AI、Web |
C# 語法特色速查
C# 語法現代、簡潔,有幾個特色是面試常考、日常也常用的,熟悉它們能讓程式碼更安全、更易讀:
LINQ(Language Integrated Query)
LINQ 是 C# 最強大的特性之一,讓你用類似 SQL 的語法操作任何集合(List、陣列、資料庫、XML)。一旦用習慣,寫不帶 LINQ 的 C# 會很難受。
Deferred Execution(延遲執行)
LINQ 查詢是 lazy(懶) 的:建立查詢時不執行,只有在實際迭代(foreach、.ToList()、.Count()...)時才執行。這意味著可以先建立查詢描述,之後再決定是否執行,但也要注意多次迭代會多次執行查詢。
async / await
C# 的 async/await 是非同步程式設計的核心,讓非同步程式碼讀起來像同步程式碼。在 ASP.NET Web API 裡幾乎所有 I/O 操作都應該非同步。
Task vs Task<T>
Task 代表「沒有返回值的非同步操作」(等同 void);Task<T> 代表「返回 T 型別結果的非同步操作」。
避免 async void
async void 無法被 await,例外發生時無法被捕獲,會直接崩潰整個程式。唯一例外是事件處理器(event handler)。其他情況一律用 async Task。
Deadlock 陷阱
在 ASP.NET 環境中,不要對 async 方法呼叫 .Result 或 .Wait()(同步阻塞),這會造成 deadlock。永遠用 await 等待。
ASP.NET Web API 基礎
ASP.NET Core 的 Web API 採用 MVC 架構,Controller 負責處理 HTTP 請求。以下是一個完整的 CRUD Controller 骨架:
Middleware Pipeline
ASP.NET Core 的請求依序通過 Middleware Pipeline:Authentication → Authorization → Routing → Controller。每個 Middleware 可以決定要不要繼續傳遞請求。在 Program.cs 裡用 app.UseXxx() 的順序很重要,先加的先執行。
Dependency Injection(DI)
DI 是 ASP.NET Core 的核心設計:類別不自己 new 依賴,而是透過建構函數宣告需要什麼,由框架負責「注入」。好處是低耦合、易測試。
| 生命週期 | 說明 | 適合場景 | 注冊方式 |
|---|---|---|---|
| Singleton | 整個應用程式生命週期只有一個實例,所有請求共用 | 快取、設定、logging | AddSingleton<T>() |
| Scoped | 每個 HTTP 請求建立一個新實例,同一請求內共用 | DbContext、業務服務 | AddScoped<T>() |
| Transient | 每次注入都建立新實例 | 輕量、無狀態的工具類 | AddTransient<T>() |
面試常考題
Q1. C# 的 struct 和 class 差異?
struct 是 Value Type,存在 Stack 上,賦值時複製整個值(互相獨立)。class 是 Reference Type,存在 Heap 上,賦值時複製的是參考(指向同一個物件)。struct 適合小型不可變資料(Point、Color);class 適合複雜物件。
Q2. LINQ 的 deferred execution 是什麼意思?
LINQ 查詢在建立時不立即執行,只是描述「要怎麼查」。真正執行發生在迭代時(foreach、ToList()、Count()、First()...)。好處是可以組合多個查詢再一次執行;壞處是若資料源在查詢建立後被修改,結果會反映最新狀態。
Q3. async/await 和 Thread 的差異?
Thread 是 OS 層級的執行緒,佔用真實資源(~1MB stack)。async/await 是非同步模型,等待 I/O 時釋放執行緒去做其他事,I/O 完成後繼續。結果是:1000 個並發 HTTP 請求,Thread 模型需要 1000 個執行緒;async 模型可能只需幾十個執行緒,大幅提升吞吐量。
Q4. interface 和 abstract class 的使用時機?
interface 定義「能做什麼」(行為契約),一個 class 可以實作多個 interface。abstract class 定義「是什麼」(繼承關係),可以包含部分實作。DI 幾乎都用 interface(IUserService)。若類別之間有 is-a 關係且需共用程式碼,用 abstract class。
Q5. DI 中 Scoped 和 Singleton 的差異?
Singleton:整個應用程式只有一個實例,所有請求共用,必須是執行緒安全的。Scoped:每個 HTTP 請求有獨立實例,同一請求內共用(例如同一請求的 Controller 和 Service 共用同一個 DbContext),不需要執行緒安全考量。
Q6. .NET 5/6/7/8 和 .NET Framework 的差異?
.NET Framework(1.0–4.8)只能跑在 Windows,已進入維護模式。.NET Core / .NET 5+(統一品牌)是跨平台的現代版本,效能更好、更輕量。新專案全部用 .NET 8(目前 LTS),不要用舊的 .NET Framework,除非維護遺留系統。
上一篇
EP.01 — C語言
指標與記憶體管理
下一篇
EP.03
即將推出