深入解析 C#, 4/e (C# in Depth, 4/e)
內容描述
C#語言簡潔優雅,精妙強大,是當今編程語言的集大成者,
功能不斷推陳出新,受到眾多開發人員的推崇。
本書是C#領域不可多得的經典著作,新版重磅升級,不僅重新組織了內容,
還全面更新並細致剖析了C#6和C#7的新增特性,為讀者奉上知識盛宴。
作者在詳盡展示C#各個知識點的同時,註重從現象中挖掘本質,
解讀語言背後的設計思想,深入探究了C#的核心概念和經典特性,
並將這些特性融入代碼示例,幫助讀者順暢使用C#,享受使用C#編程的樂趣。
目錄大綱
目錄
第 一部分 C#背景介紹
第 1章 大浪淘沙 2
1.1 一門與時俱進的語言 2
1.1.1 類型系統——全能型助手 3
1.1.2 代碼更簡潔 4
1.1.3 使用LINQ簡化數據訪問 8
1.1.4 異步 8
1.1.5 編碼效率與執行效率之間的取捨 9
1.1.6 快速迭代:使用小版本號 10
1.2 一個與時俱進的平臺 11
1.3 一個與時俱進的社區 12
1.4 一本與時俱進的好書 13
1.4.1 內容詳略得當 13
1.4.2 使用Noda Time作為示例 14
1.4.3 術語選擇 14
1.5 小結 15
第二部分 從C# 2到C#5
第 2章 C# 2 18
2.1 泛型 18
2.1.1 示例:泛型誕生前的集合 19
2.1.2 泛型降臨 21
2.1.3 泛型的適用範圍 25
2.1.4 方法類型實參的類型推斷 26
2.1.5 類型約束 28
2.1.6 default運算符和typeof運算符 30
2.1.7 泛型類型初始化與狀態 32
2.2 可空值類型 34
2.2.1 目標:表達信息的缺失 34
2.2.2 CLR和framework的支持:Nullable結構體 35
2.2.3 語言層面支持 38
2.3 簡化委托的創建 43
2.3.1 方法組轉換 43
2.3.2 匿名方法 44
2.3.3 委托的兼容性 45
2.4 迭代器 46
2.4.1 迭代器簡介 47
2.4.2 延遲執行 48
2.4.3 執行yield語句 49
2.4.4 延遲執行的重要性 50
2.4.5 處理finally塊 51
2.4.6 處理finally的重要性 53
2.4.7 迭代器實現機制概覽 54
2.5 一些小的特性 58
2.5.1 局部類型 59
2.5.2 靜態類 60
2.5.3 屬性的getter/setter訪問分離 61
2.5.4 命名空間別名 61
2.5.5 編譯指令 63
2.5.6 固定大小的緩沖區 64
2.5.7 InternalsVisibleTo 65
2.6 小結 65
第3章 C# 3:LINQ及相關特性 66
3.1 自動實現的屬性 66
3.2 隱式類型 67
3.2.1 類型術語 67
3.2.2 隱式類型的局部變量 68
3.2.3 隱式類型的數組 69
3.3 對象和集合的初始化 71
3.3.1 對象初始化器和集合初始化器簡介 71
3.3.2 對象初始化器 72
3.3.3 集合初始化器 74
3.3.4 僅用單一表達式就能完成初始化的好處 75
3.4 匿名類型 76
3.4.1 基本語法和行為 76
3.4.2 編譯器生成類型 78
3.4.3 匿名類型的局限性 79
3.5 lambda表達式 80
3.5.1 lambda表達式語法簡介 81
3.5.2 捕獲變量 82
3.5.3 表達式樹 89
3.6 擴展方法 91
3.6.1 聲明擴展方法 91
3.6.2 調用擴展方法 92
3.6.3 擴展方法的鏈式調用 93
3.7 查詢表達式 94
3.7.1 從C#到C#的查詢表達式轉換 95
3.7.2 範圍變量和隱形標識符 95
3.7.3 選擇使用哪種LINQ語法 96
3.8 終極形態:LINQ 97
3.9 小結 98
第4章 C# 4:互操作性提升 99
4.1 動態類型 99
4.1.1 動態類型介紹 100
4.1.2 超越反射的動態行為 104
4.1.3 動態行為機制速覽 108
4.1.4 動態類型的局限與意外 111
4.1.5 動態類型的使用建議 115
4.2 可選形參和命名實參 116
4.2.1 帶默認值的形參和帶名字的實參 117
4.2.2 如何決定方法調用的含義 118
4.2.3 對版本號的影響 119
4.3 COM互操作性提升 121
4.3.1 鏈接主互操作程序集 121
4.3.2 COM組件中的可選形參 123
4.3.3 命名索引器 124
4.4 泛型型變 125
4.4.1 泛型型變示例 125
4.4.2 接口和委托聲明中的變體語法 126
4.4.3 變體的使用限制 127
4.4.4 泛型型變實例 129
4.5 小結 130
第5章 編寫異步代碼 131
5.1 異步函數簡介 132
5.1.1 異步問題初體驗 133
5.1.2 拆分第 一個例子 134
5.2 對異步模式的思考 135
5.2.1 關於異步執行本質的思考 136
5.2.2 同步上下文 137
5.2.3 異步方法模型 138
5.3 async方法聲明 139
5.3.1 async方法的返回類型 140
5.3.2 async方法的參數 141
5.4 await表達式 141
5.4.1 可等待模式 142
5.4.2 await表達式的限制條件 144
5.5 返回值的封裝 145
5.6 異步方法執行流程 146
5.6.1 await的操作對象與時機 146
5.6.2 await表達式的運算 147
5.6.3 可等待模式成員的使用 150
5.6.4 異常拆封 151
5.6.5 完成方法 152
5.7 異步匿名函數 156
5.8 C# 7自定義task類型 157
5.8.1 99.9%的情況:ValueTask 158
5.8.2 剩下0.1%的情況:創建自定義task類型 160
5.9 C# 7.1中的異步Main方法 161
5.10 使用建議 162
5.10.1 使用ConfigureAwait避免上下文捕獲(擇機使用) 163
5.10.2 啟動多個獨立task以實現並行 164
5.10.3 避免同步代碼和異步代碼混用 165
5.10.4 根據需要提供取消機制 165
5.10.5 測試異步模式 165
5.11 小結 166
第6章 異步原理 167
6.1 生成代碼的結構 168
6.1.1 樁方法:準備和開始第 一步 171
6.1.2 狀態機的結構 172
6.1.3 MoveNext()方法(整體介紹) 175
6.1.4 SetStateMachine方法以及狀態機的裝箱事宜 177
6.2 一個簡單的MoveNext()實現 177
6.2.1 一個完整的具體示例 178
6.2.2 MoveNext()方法的通用結構 179
6.2.3 詳探await表達式 181
6.3 控制流如何影響MoveNext() 183
6.3.1 await表達式之間的控制流很簡單 183
6.3.2 在循環中使用await 184
6.3.3 在try / finally塊中使用await表達式 185
6.4 執行上下文和執行流程 188
6.5 再探自定義task類型 189
6.6 小結 190
第7章 C# 5附加特性 191
7.1 在foreach循環中捕獲變量 191
7.2 調用方信息attribute 193
7.2.1 基本行為 193
7.2.2 日誌 194
7.2.3 簡化INotifyPropertyChanged的實現 195
7.2.4 調用方信息attribute的小眾使用場景 196
7.2.5 舊版本.NET使用調用方信息attribute 201
7.3 小結 202
第三部分 C# 6
第8章 極簡屬性和表達式主體成員 204
8.1 屬性簡史 204
8.2 自動實現屬性的升級 206
8.2.1 只讀的自動實現屬性 206
8.2.2 自動實現屬性的初始化 207
8.2.3 結構體中的自動實現屬性 208
8.3 表達式主體成員 210
8.3.1 簡化只讀屬性的計算 210
8.3.2 表達式主體方法、索引器和運算符 213
8.3.3 C# 6中表達式主體成員的限制 214
8.3.4 表達式主體成員使用指南 216
8.4 小結 218
第9章 字符串特性 219
9.1 NET中的字符串格式化回顧 219
9.1.1 簡單字符串格式化 219
9.1.2 使用格式化字符串來實現自定義格式化 220
9.1.3 屬地化 221
9.2 內插字符串字面量介紹 224
9.2.1 簡單內插 224
9.2.2 使用內插字符串字面量格式化字符串 225
9.2.3 內插原義字符串字面量 225
9.2.4 編譯器對內插字符串字面量的處理(第 1部分) 226
9.3 使用FormattableSting實現屬地化 227
9.3.1 編譯器對內插字符串字面量的處理(第 2部分) 228
9.3.2 在特定culture下格式化一個FormattableString 229
9.3.3 FormattableString的其他用途 230
9.3.4 在舊版本.NET中使用FormattableString 233
9.4 使用指南和使用限制 234
9.4.1 適合開發人員和機器,但可能不適合最終用戶 235
9.4.2 關於內插字符串字面量的硬性限制 236
9.4.3 何時可以用但不應該用 238
9.5 使用nameof訪問標識符 239
9.5.1 nameof的第 一個例子 239
9.5.2 nameof的一般用法 241
9.5.3 使用nameof的技巧與陷阱 243
9.6 小結 246
第 10章 簡潔代碼的特性“盛宴” 247
10.1 using static指令 247
10.1.1 引入靜態成員 247
10.1.2 using static與擴展方法 250
10.2 對象初始化器和集合初始化器特性增強 252
10.2.1 對象初始化器中的索引器 252
10.2.2 在集合初始化器中使用擴展方法 256
10.2.3 測試代碼與產品代碼 259
10.3 空值條件運算符 260
10.3.1 簡單、安全地解引用 260
10.3.2 關於空值條件運算符的更多細節 261
10.3.3 處理布爾值比較 262
10.3.4 索引器與空值條件運算符 263
10.3.5 使用空值條件運算符提升編程效率 263
10.3.6 空值條件運算符的局限性 265
10.4 異常過濾器 265
10.4.1 異常過濾器的語法和語義 266
10.4.2 重試操作 270
10.4.3 記錄日誌的“副作用” 272
10.4.4 單個、有針對性的日誌過濾器 273
10.4.5 為何不直接拋出異常 273
10.5 小結 274
第四部分 C# 7及其後續版本
第 11章 使用元組進行組合 277
11.1 元組介紹 277
11.2 元組字面量和元組類型 278
11.2.1 語法 278
11.2.2 元組字面量推斷元素名稱(C# 7.1) 280
11.2.3 元組用作變量的容器 281
11.3 元組類型及其轉換 285
11.3.1 元組字面量的類型 285
11.3.2 從元組字面量到元組類型的轉換 287
11.3.3 元組類型之間的轉換 290
11.3.4 類型轉換的應用 292
11.3.5 繼承時的元素名稱檢查 292
11.3.6 等價運算符與不等價運算符(C# 7.3) 293
11.4 CLR 中的元組 294
11.4.1 引入System.ValueTuple<> 294
11.4.2 處理元素名稱 294
11.4.3 元組類型轉換的實現 296
11.4.4 元組的字符串表示 296
11.4.5 一般等價比較和排序比較 297
11.4.6 結構化等價比較和排序比較 298
11.4.7 獨素元組和巨型元組 299
11.4.8 非泛型ValueTuple結構體 300
11.4.9 擴展方法 301
11.5 元組的替代品 301
11.5.1 System.Tuple<> 301
11.5.2 匿名類型 301
11.5.3 命名類型 302
11.6 元組的使用建議 302
11.6.1 非公共API以及易變的代碼 303
11.6.2 局部變量 303
11.6.3 字段 304
11.6.4 元組和動態類型不太搭調 305
11.7 小結 306
第 12章 分解與模式匹配 307
12.1 分解元組 307
12.1.1 分解成新變量 308
12.1.2 通過分解操作為已有變量或者屬性賦值 310
12.1.3 元組字面量分解的細節 313
12.2 非元組類型的分解操作 314
12.2.1 實例分解方法 314
12.2.2 擴展分解方法與重載 315
12.2.3 編譯器對於Deconstruct調用的處理 316
12.3 模式匹配簡介 317
12.4 C# 7.0可用的模式 319
12.4.1 常量模式 319
12.4.2 類型模式 320
12.4.3 var模式 323
12.5 模式匹配與is運算符的搭配使用 324
12.6 在switch語句中使用模式 325
12.6.1 哨兵語句 326
12.6.2 case標簽中的模式變量的作用域 328
12.6.3 基於模式的switch語句的運算順序 329
12.7 對模式特性使用的思考 330
12.7.1 發現分解的時機 330
12.7.2 發現模式匹配的使用時機 331
12.8 小結 331
第 13章 引用傳遞提升執行效率 332
13.1 回顧:ref知多少 333
13.2 ref局部變量和ref return 336
13.2.1 ref局部變量 336
13.2.2 ref return 341
13.2.3 條件運算符 :和ref值(C# 7.2) 343
13.2.4 ref readonly(C# 7.2) 343
13.3 in參數(C# 7.2) 345
13.3.1 兼容性考量 346
13.3.2 in參數驚人的不可變性:外部修改 347
13.3.3 使用in參數進行方法重載 348
13.3.4 in參數的使用指導 348
13.4 將結構體聲明為只讀(C# 7.2) 350
13.4.1 背景:只讀變量的隱式復制 350
13.4.2 結構體的只讀修飾符 352
13.4.3 XML序列化是隱式讀寫屬性 353
13.5 使用ref參數或者in參數的擴展方法(C# 7.2) 354
13.5.1 在擴展方法中使用ref/in參數來規避復制 354
13.5.2 ref和in擴展方法的使用限制 355
13.6 類ref結構體(C# 7.2) 357
13.6.1 類ref結構體的規則 357
13.6.2 Span和棧內存分配 358
13.6.3 類ref結構體的IL表示 362
13.7 小結 362
第 14章 C# 7的代碼簡潔之道 363
14.1 局部方法 363
14.1.1 局部方法中的變量訪問 364
14.1.2 局部方法的實現 367
14.1.3 使用指南 371
14.2 out變量 373
14.2.1 out參數的內聯變量聲明 374
14.2.2 C# 7.3 關於out變量和模式變量解除的限制 374
14.3 數字字面量的改進 375
14.3.1 二進制整型字面量 375
14.3.2 下劃線分隔符 376
14.4 throw表達式 377
14.5 default字面量(C# 7.1) 377
14.6 非尾部命名實參 379
14.7 私有受保護的訪問權限(C# 7.2) 380
14.8 C# 7.3的一些小改進 380
14.8.1 泛型類型約束 381
14.8.2 重載決議改進 381
14.8.3 字段的attribute支持自動實現的屬性 382
14.9 小結 383
第 15章 C# 8及其後續 384
15.1 可空引用類型 384
15.1.1 可空引用類型可以解決什麽問題 385
15.1.2 在使用引用類型時改變其含義 385
15.1.3 輸入可空引用類型 387
15.1.4 編譯時和執行期的可空引用類型 387
15.1.5 damnit運算符或者bang運算符 389
15.1.6 可空引用類型遷移的經驗 391
15.1.7 未來的改進 393
15.2 switch表達式 396
15.3 嵌套模式匹配 398
15.3.1 使用模式來匹配屬性 398
15.3.2 分解模式 399
15.3.3 忽略模式中的類型 399
15.4 index和range 400
15.4.1 index與range類型和字面量 401
15.4.2 應用index和range 402
15.5 更多異步集成 403
15.5.1 使用await實現異步資源回收 403
15.5.2 使用foreach await的異步迭代 404
15.5.3 異步迭代器 407
15.6 預覽版中尚未提供的特性 408
15.6.1 默認接口方法 408
15.6.2 記錄類型 409
15.6.3 更多特性 410
15.7 歡迎加入 412
15.8 小結 412
附錄 特性與語言版本對照表 413
作者介紹
Jon Skeet
谷歌高級軟件工程師,微軟C# MVP,擁有近20年C#項目開發經驗。
自2002年來,他一直是C#社區、新聞組、國際會議和Stack Overflow網站中非常活躍的技術專家,
回答了數以萬計的C#和.NET相關問題,是Stack Overflow上的傳奇貢獻者。