本文精選 10 道經典 C# 面試題,涵蓋字符串內存模型、值類型與引用類型、委托事件、編碼與字符串長度、SQL 查詢、線程安全與鎖、數據庫連接池與異常處理、Remoting 與 WebService 對比、ListView 排序擴展、XML 遞歸遍歷等核心知識點。每題附帶標準答案與深度解析,助力面試準備與知識查漏補缺。
說明兩者在內存分配上的詳細區別。
string str = null:不分配內存空間,變量為空引用,不指向任何對象實例。string str = "":分配一個長度為 0 的字符串對象在托管堆上,變量指向這個有效的空字符串實例。null 表示「無引用」,調用任何實例成員會拋出 NullReferenceException。"" (或 String.Empty) 是一個合法的字符串對象,Length == 0,可安全調用實例方法如 ToString()、Equals()。String.IsNullOrEmpty() 可同時檢查兩種情況。字符串為引用類型且不可變,"" 可能被字符串驻留池優化為單例。
| 特性 | Class (引用類型) | Struct (值類型) |
|---|---|---|
| 內存分配 | 托管堆 | 棧 (或內嵌於包含類型中) |
| 繼承 | 支持繼承 (單繼承),可為基類 | 不可繼承 (隱式 sealed),不可為基類 |
| 默認構造函數 | 編譯器生成無參構造函數 | 無無參構造函數,成員自動初始化為 0/null |
| 賦值語義 | 引用拷貝 (指向同一對象) | 值拷貝 (創建獨立副本) |
| 可為 null | 是 | 需用 Nullable<T> 或 T? |
| 適用場景 | 複雜行為、身份標識、大型對象 | 輕量級數據結構、邏輯值語義、高頻創建銷毀 |
Class 分配在堆上,通過引用訪問;Struct 分配在棧上,按值傳遞。這是面試必考的核心區別。
在用戶控件工具欄按鈕點擊事件中,正確觸發 OnNew 事件。
if (OnNew != null)
{
OnNew(this, e); // 注意:原題代碼中委托簽名為 void OnDBOperate() 無參數,但事件觸發通常傳送 sender 和 EventArgs
// 若委托定確為 void OnDBOperate(),則調用 OnNew();
}
OnNew != null,否則無訂閱者時拋出異常var handler = OnNew; handler?.Invoke(this, e);string strTmp = "abcdefg某某某";
int i = Encoding.Default.GetBytes(strTmp).Length; // 字節長度
int j = strTmp.Length; // 字符長度
i = 13, j = 10
strTmp 含 7 個 ASCII 字符 (各 1 字節) + 3 個中文字符 (GB2312/默認編碼下各 2 字節) = 7 + 6 = 13 字節Length 返回 Char 數量 (UTF-16 代碼單元),此處為 10 個字符Encoding.Default 因系統區域設置不同而異 (中文系統通常為 GB2312/GBK),跨平台建議顯式指定 Encoding.UTF8 (中文 3 字節) 或 Encoding.Unicode (固定 2 字節)表 table1 有 ID、LastUpdateDate,用一條 SQL 獲取最後更新的事務號。
SELECT ID
FROM table1
WHERE LastUpdateDate = (SELECT MAX(LastUpdateDate) FROM table1);
LastUpdateDate 有並發相同值,可能返回多行。可用 TOP 1 ORDER BY LastUpdateDate DESC 或 ROW_NUMBER() 窗口函數確保單行ID 為自增主鍵,通常 SELECT TOP 1 ID FROM table1 ORDER BY LastUpdateDate DESC, ID DESC 更高效public void test(int i) {
lock(this) {
if (i > 10) {
i--;
test(i); // 遞歸調用
}
}
}
不會發生死鎖。
int 是值類型,按值傳遞。每次遞歸傳入的是副本,修改不影響外層變量lock(this) 基於 Monitor 可重入),遞歸調用同一方法同一實例會直接獲得鎖,不阻塞ref int i 或引用類型 object,則共享同一變量/對象,但因鎖可重入仍不會死鎖,只會正常遞歸執行OleDbConnection conn = new OleDbConnection(connStr);
try { conn.Open(); ... }
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
finally { if (conn.State != ConnectionState.Closed) conn.Close(); }
能。關鍵條件:連接字符串完全一致 (含空格、屬性順序)。finally 中 Close() 將連接返回池中,而非真正關閉底層連接。
不能保證。catch 僅捕獲 try 塊內異常。finally 中的 conn.Close() 或 MessageBox.Show 若拋出異常將無法被捕獲,導致原始異常丟失或程序崩潰。最佳實踐:finally 內部再包裹 try-catch,或使用 using 語句自動釋放。
| 維度 | WebService (ASMX/WCF) | .NET Remoting |
|---|---|---|
| 傳輸協議 | HTTP/HTTPS (穿透防火牆強) | TCP/IP (默認), HTTP 等可擴展 |
| 序列化 | XmlSerializer / DataContractSerializer (SOAP/JSON) | BinaryFormatter / SoapFormatter (二進制高效) |
| 性能 | 文本序列化開銷大,較低 | 二進制序列化,高性能 |
| 互操作性 | 跨平台、跨語言 (標準 SOAP/REST) | 僅限 .NET 平台 |
| 部署 | IIS 託管,易部署 | 需自行宿主 (Windows Service, Console, IIS) |
| 適用場景 | 跨組織、異構系統集成、Web API | .NET 內部高性能分布式組件通信 |
現代觀點:Remoting 屬於舊技術,新項目推薦 WCF / gRPC / Web API (ASP.NET Core)。
ListView,處理 ColumnClick 事件ColumnHeader.Index)IComparer<ListViewItem>)ListView.ListViewItemSorter = comparer,然後 Sort()private void listView_ColumnClick(object sender, ColumnClickEventArgs e) {
var comparer = new ListViewItemComparer(e.Column, sortOrder);
listView.ListViewItemSorter = comparer;
listView.Sort();
// 切換 sortOrder (Ascending/Descending)
}
<FileSystem>
<DriverC>
<Dir DirName="MSDOS622">
<File FileName="Command.com" />
</Dir>
<File FileName="MSDOS.SYS" />
<File FileName="IO.SYS" />
</DriverC>
</FileSystem>
void FindFile(XmlNode node) {
// 1. 處理當前節點
if (node.Name == "File") {
string fileName = node.Attributes["FileName"].Value;
Console.WriteLine(fileName); // 或收集到列表
}
// 2. 遞歸處理子節點
foreach (XmlNode child in node.ChildNodes) {
FindFile(child);
}
}
// 調用入口
XmlDocument doc = new XmlDocument();
doc.Load("filesystem.xml");
FindFile(doc.DocumentElement);
XmlDocument (DOM) 或 XmlReader (流式) 解析XmlReader 適合大文件單次只讀這 10 道題覆蓋了 C# 基礎類型系統、內存模型、委托事件、字符編碼、SQL 基礎、多線程同步、ADO.NET 最佳實踐、分布式技術選型、WinForms 控件擴展、XML 處理等核心領域。面試時除給出正確答案外,能結合 原理、最佳實踐、常見坑、現代替代方案 進行延伸闡述,將顯著提升評價。建議針對薄弱項深入閱讀官方文檔與 CLR Via C# 等經典著作。