引 言
第一部分 基礎知識
第1章 .NET基礎知識 2
1.1 .NET框架介紹 2
1.2 .NET框架發展史 3
1.3 .NET框架的主要成員 5
1.3.1 兩步編譯與跨平颱 5
1.3.2 CLR 6
1.3.3 CLI 7
1.3.4 CTS和CLS 8
1.3.5 框架類庫(FCL) 8
1.3.6 基礎類庫(BCL) 9
1.4 程序集 10
1.4.1 反嚮工程—使用ILSpy觀察IL 10
1.4.2 程序集與托管模塊 11
1.4.3 程序集的部署 18
1.5 .NET程序的編譯:IL與JIT 20
1.5.1 什麼是IL(CIL) 21
1.5.2 初識IL 21
1.5.3 System.Reflection.Emit 31
1.5.4 即時編譯(JIT) 33
1.5.5 運行時的驗證 34
1.5.6 Visual Studio的編譯模式與本地代碼的優化 34
1.5.7 托管代碼與非托管代碼的互操作性 35
1.6 CLR啓動與Hello World的運行 36
1.7 本章小結 37
1.8 思考題 37
第2章 C#類型基礎(上) 38
2.1 公共類型係統 38
2.2 堆與棧 40
2.2.1 堆 40
2.2.2 棧 41
2.3 引用類型的內存分配 42
2.3.1 字段的對齊 44
2.3.2 同步塊索引 45
2.3.3 方法錶指針和類型對象 45
2.3.4 靜態字段和屬性 46
2.4 使用WinDbg探查內存 46
2.4.1 WinDbg簡易命令速查 47
2.4.2 使用WinDbg探查引用類型 47
2.4.3 引用類型的復製 52
2.5 值類型 53
2.5.1 基元類型 54
2.5.2 值類型的內存分配 54
2.5.3 值類型的構造函數 56
2.5.4 何時考慮使用值類型 57
2.5.5 值類型是密封的 58
2.5.6 值類型和引用類型的區彆與聯係 58
2.5.7 嵌套:值類型與引用類型 58
2.6 裝箱和拆箱 59
2.6.1 裝箱的過程 59
2.6.2 拆箱的過程 60
2.6.3 如何避免拆箱和裝箱 60
2.7 本章小結 61
2.8 思考題 61
第3章 C#類型基礎(下) 62
3.1 類型的非方法成員 62
3.1.1 常量 62
3.1.2 字段 63
3.1.3 無參屬性 64
3.1.4 有參屬性 66
3.1.5 屬性的意義 67
3.2 類型的構造函數和析構函數 67
3.2.1 靜態類 67
3.2.2 實例構造函數(引用類型) 68
3.2.3 實例構造函數(值類型) 69
3.2.4 靜態構造函數 69
3.2.5 構造函數的執行順序 70
3.2.6 析構函數 71
3.3 類型的普通方法成員 72
3.3.1 方法錶 73
3.3.2 使用WinDbg探查方法錶 73
3.3.3 方法槽錶與方法描述錶在JIT前後的變化 75
3.3.4 方法調用 77
3.3.5 方法參數的按值傳遞和按引用傳遞 80
3.4 類型轉換 82
3.4.1 將一個對象轉換為它的基類型 83
3.4.2 將一個對象轉換為它的派生類型 84
3.4.3 基元類型的類型轉換 84
3.4.4 自定義類型轉換 84
3.5 System.Object類型的主要方法 85
3.6 本章小結 90
3.7 思考題 91
第4章 C#和麵嚮對象 92
4.1 麵嚮對象程序設計 92
4.2 繼承 93
4.2.1 方法錶與繼承 94
4.2.2 再論Call與Callvirt 94
4.2.3 IL中修飾方法的關鍵字 95
4.2.4 方法的重載、重寫和隱藏 96
4.2.5 值類型的方法調用 100
4.3 接口和多態 101
4.3.1 抽象類與Is A關係 102
4.3.2 接口與Has A關係 102
4.3.3 顯式接口實現 103
4.3.4 顯式接口實現與泛型接口 104
4.3.5 抽象類VS接口 105
4.3.6 接口不繼承自Object 106
4.3.7 接口方法分派 106
4.4 麵嚮對象編程五大原則(SOLID) 106
4.4.1 單一職責原則 107
4.4.2 開閉原則 107
4.4.3 裏氏代換原則 111
4.4.4 接口隔離原則 111
4.4.5 依賴倒轉原則 112
4.5 本章小結 112
4.6 思考題 113
第5章 字符串 114
5.1 字符 114
5.2 字符串的特性 115
5.2.1 字符串與普通的引用類型相比 116
5.2.2 IL中創建字符串 116
5.2.3 字符串的不變性 117
5.2.4 通過成員來證明不變性 118
5.2.5 為什麼要這麼設計 119
5.3 字符串駐留 119
5.4 字符串的相加 121
5.5 不變性隻是針對托管代碼 124
5.6 本章小結 125
5.7 思考題 125
第6章 垃圾迴收 126
6.1 垃圾迴收的概念 127
6.1.1 GC堆的構造 127
6.1.2 識彆垃圾 128
6.1.3 壓縮 136
6.1.4 C#的GC規則總結 136
6.2 垃圾迴收策略 136
6.2.1 Dispose方法和IDisposible接口 136
6.2.2 析構函數(終結器) 137
6.2.3 如何迴收托管資源 140
6.2.4 如何迴收非托管資源 142
6.2.5 using關鍵字 143
6.2.6 總結:怎樣實現垃圾迴收策略 144
6.3 GC的工作模式 145
6.3.1 工作站模式 145
6.3.2 服務器模式 146
6.4 大對象 146
6.5 本章小結 147
6.6 思考題 147
第7章 異常與異常處理 148
7.1 C#的異常處理 149
7.1.1 try 149
7.1.2 catch 149
7.1.3 finally 150
7.1.4 結構化異常處理 152
7.1.5 throw和throw ex 153
7.2 IL中的異常處理機製 155
7.3 開發中的異常處理 159
7.3.1 提高程序的健壯性 159
7.3.2 使用.NET自帶的日誌類型 159
7.4 本章小結 163
7.5 思考題 163
第二部分 C#特性
第8章 委托和事件 166
8.1 委托 166
8.1.1 委托初探 166
8.1.2 使用委托達到代碼復用的目的 168
8.1.3 委托的協變和逆變 171
8.1.4 委托的本質 171
8.1.5 委托鏈與多路廣播 174
8.1.6 委托的異步調用 176
8.2 事件 176
8.2.1 事件初探 177
8.2.2 事件的本質 180
8.2.3 Winform中的經典事件:單擊按鈕 182
8.2.4 Windows消息機製簡介 183
8.2.5 觀察者模式 185
8.3 本章小結 189
8.4 思考題 189
第9章 泛型 190
9.1 泛型方法 190
9.1.1 類型安全與代碼爆炸 191
9.1.2 泛型類型的靜態成員 193
9.1.3 泛型與繼承 194
9.1.4 泛型約束 194
9.1.5 泛型委托 195
9.1.6 使用泛型委托達到代碼復用的目的 196
9.2 可空類型 197
9.3 協變和逆變 200
9.3.1 可變性 200
9.3.2 通過反射調用泛型方法 207
9.4 本章小結 208
9.5 思考題 208
第10章 反射 209
10.1 初識反射 209
10.1.1 獲得類型的基本信息 210
10.1.2 獲得類型成員和方法調用 211
10.1.3 加載程序集(晚期綁定) 215
10.1.4 反射與泛型 216
10.2 反射的應用場景 218
10.3 反射的性能問題 218
10.3.1 方法反射調用有多慢 218
10.3.2 通過其他方法優化反射調用方式 220
10.3.3 反射優化的性能比較 225
10.4 反射的應用:一個簡單的ORM 225
10.4.1 通過反射和特性建立錶格和實體的聯係 226
10.4.2 為實體增加主鍵 227
10.4.3 建立本地數據庫 228
10.4.4 建立錶格 228
10.4.5 刪除錶格 231
10.4.6 為錶格插入數據 231
10.4.7 選擇數據 233
10.4.8 多錶聯查怎麼辦 234
10.4.9 優化ORM:使用委托來獲得值 235
10.4.10 完整的實現代碼 235
10.4.11 小結 242
10.5 本章小結 242
10.6 思考題 243
第11章 C#的數據結構 244
11.1 IEnumerable 244
11.1.1 迭代器模式 244
11.1.2 什麼是IEnumerable 245
11.1.3 實現一個繼承IEnumerable的類型 245
11.1.4 yield的延遲執行特性 256
11.1.5 IEnumerable是一個可枚舉序列,但不是容器 257
11.1.6 在迭代的過程中改變集閤的狀態 259
11.1.7 IEnumerable的缺點和總結 259
11.2 IEnumerable的派生類 260
11.2.1 Array 260
11.2.2 ArrayList 261
11.2.3 IDictionary 262
11.3 IEnumerable的派生類 272
11.3.1 IList 272
11.3.2 LinkedList 272
11.3.3 Queue 281
11.3.4 Stack 283
11.3.5 IDictionary 284
11.3.6 ISet 287
11.4 常用數據結構特徵以及操作時間復雜度 288
11.5 如何選擇數據結構 289
11.6 本章小結 289
11.7 思考題 290
第12章 LINQ的準備工作 291
12.1 匿名函數、捕獲變量與閉包 291
12.1.1 匿名函數 291
12.1.2 演示捕獲變量 293
12.1.3 閉包 300
12.2 LINQ的準備工作 301
12.2.1 自動實現的屬性 302
12.2.2 隱式類型的局部變量 302
12.2.3 匿名類型 303
12.2.4 擴展方法 305
12.3 Lambda錶達式和錶達式樹 306
12.3.1 從匿名函數到Lambda錶達式 306
12.3.2 錶達式簡介 308
12.3.3 構建簡單的錶達式樹 309
12.3.4 錶達式樹與反射 311
12.4 本章小結 315
12.5 思考題 315
第13章 LINQ to Object 316
13.1 LINQPad 316
13.2 Enumerable是什麼 318
13.3 使用Northwind數據源演示查詢操作 318
13.4 投影操作符與過濾操作符 318
13.4.1 Select整個錶 318
13.4.2 Select部分列 319
13.4.3 Select結閤Lambda錶達式 320
13.4.4 使用where進行過濾 320
13.4.5 SelectMany 321
13.4.6 Distinct 324
13.5 排序操作符 325
13.6 分組操作符 325
13.7 通過Let聲明局部變量 328
13.8 連接操作符 329
13.8.1 使用join子句的內連接 330
13.8.2 使用join into子句進行外連接 330
13.9 其他常用的操作符 331
13.10 延遲執行 333
13.11 查詢錶達式和方法語法 335
13.12 本章小結 336
13.13 思考題 336
第14章 LINQ to SQL 337
14.1 IQueryable 337
14.2 IQueryable與 IEnumerable的異同 338
14.3 數據庫操作 339
14.3.1 弱類型實體集 339
14.3.2 Entity Framework 340
14.3.3 Repository模式 342
14.4 使用LINQ to Entity Framework 342
14.4.1 Database First 342
14.4.2 Model First 346
14.4.3 Code First 347
14.5 錶達式樹轉化為SQL 348
14.5.1 準備工作 349
14.5.2 實現IQueryable 351
14.5.3 實現IQueryProvider 352
14.5.4 測試IQueryable的運行流程 354
14.5.5 錶達式查看器 355
14.5.6 第一步:解析Where錶達式 355
14.5.7 第二步:解析Where Lambda錶達式 357
14.5.8 錶達式樹轉化為SQL的總結 360
14.6 LINQ與EF的性能問題 361
14.6.1 避免Select N+1 361
14.6.2 避免重復枚舉同一序列 362
14.6.3 避免毫無必要地枚舉整個序列 363
14.6.4 Entity Framework的預熱 364
14.6.5 AsNoTracking方法 365
14.6.6 簡化傳入字符串排序的代碼 365
14.7 LINQ to Rx 370
14.7.1 事件流序列操作LINQ化 371
14.7.2 事件的限流 372
14.7.3 本質:推模型和拉模型 373
14.8 本章小結 373
14.9 思考題 374
第15章 動態語言運行時 375
15.1 dynamic關鍵字簡介 375
15.1.1 動態類型簡化晚期綁定 376
15.1.2 動態類型簡化COM互操作 378
15.1.3 動態類型相比泛型更加靈活 379
15.1.4 使用ExpandoObject創建動態類型 380
15.1.5 動態類型的好處 381
15.1.6 動態類型的限製 381
15.2 動態類型的原理 382
15.2.1 調用點 382
15.2.2 使用C# object類型模擬動態類型 383
15.2.3 建立調用點 384
15.2.4 初始化調用點 384
15.2.5 使用調用點的目標 385
15.2.6 DLR的緩存策略 386
15.3 本章小結 387
15.4 思考題 387
第16章 C# 6與C# 7的重要特性 388
16.1 C# 6的主要特性 388
16.1.1 自動屬性的再次進化 388
16.1.2 簡易函數錶達式寫法 390
16.1.3 字符串插值 392
16.1.4 使用static using調用靜態類方法 392
16.1.5 判定null的簡寫操作符. 393
16.1.6 異常過濾 394
16.1.7 nameof運算符 394
16.2 C# 7的主要特性 395
16.2.1 數字字麵量 395
16.2.2 改進的out關鍵字 396
16.2.3 模式匹配 397
16.2.4 C# 7的值類型元組 399
16.2.5 解構 402
16.2.6 局部函數 405
16.2.7 引用返迴值和引用局部變量 410
16.2.8 更多的錶達式體成員 414
16.2.9 在更多的地方拋齣異常 415
16.2.10 具有值類型的引用語義 415
16.3 C# 8前瞻 416
16.4 本章小結 417
16.5 思考題 417
第三部分 多綫程和異步
第17章 多綫程概念 420
17.1 進程和綫程 420
17.1.1 操作係統簡單發展史 420
17.1.2 進程 421
17.1.3 進程調度 424
17.1.4 進程的上下文切換 424
17.1.5 綫程 425
17.1.6 單核CPU多綫程是否能夠提高性能 428
17.2 .NET中的進程與應用程序域 428
17.2.1 .NET中的進程(托管進程) 428
17.2.2 進程間通信 428
17.2.3 使用剪貼闆實現進程間通信 429
17.2.4 應用程序域 431
17.3 .NET中的綫程(托管綫程)與Thread類的基本使用 432
17.3.1 創建綫程 433
17.3.2 綫程命名 433
17.3.3 前颱綫程和後颱綫程 434
17.3.4 綫程的狀態 435
17.3.5 嚮綫程傳遞數據 437
17.3.6 異常處理 438
17.4 綫程池 439
17.4.1 綫程池是如何管理綫程的 439
17.4.2 綫程池的綫程調度策略 440
17.4.3 使用綫程池:顯式操作 441
17.4.4 使用綫程池:異步委托 442
17.4.5 使用綫程池:通過任務 442
17.5 綫程局部存儲區(TLS) 443
17.5.1 使用[ThreadStatic]特性 443
17.5.2 使用Thread類上的兩個方法:GetData和SetData 444
17.5.3 使用ThreadLocal 445
17.6 本章小結 446
17.7 思考題 447
第18章 多綫程同步 448
18.1 多綫程同步的概念 448
18.2 鎖:基元構造 455
18.3 用戶模式構造 456
18.3.1 同步問題的提齣 456
18.3.2 JIT優化、有序性和指令重排 457
18.3.3 C#的內存模型 459
18.3.4 可見性、有序性、內存柵欄與volatile關鍵字 460
18.3.5 避免使用volatile 464
18.3.6 互鎖構造 465
18.3.7 Interlocked Anything模式 466
18.3.8 使用用戶模式構造的例子 467
18.3.9 實現自鏇鎖 468
18.3.10 SpinLock 469
18.4 內核模式構造 470
18.4.1 通過WaitHandle操作內核對象 471
18.4.2 事件構造 472
18.4.3 信號量構造 477
18.4.4 使用信號量實現鎖 478
18.4.5 互斥量構造 478
18.4.6 基元構造鎖總結 479
18.5 鎖:混閤構造 480
18.5.1 一個簡單的混閤鎖 481
18.5.2 優化DIY混閤鎖:使鎖支持遞歸和自鏇 482
18.5.3 最常用的鎖:Monitor的工作原理 484
18.5.4 Monitor的遞歸調用 485
18.5.5 如何選擇同步對象 486
18.6 .NET 4中新增的輕量級同步工具 488
18.6.1 ManualResetEventSlim和SemaphoreSlim類 489
18.6.2 ReaderWriterLockSlim類 489
18.7 這麼多鎖:總結 491
18.8 綫程安全的集閤類 491
18.9 本章小結 494
18.10 思考題 494
第19章 .NET 4之前的異步編程 495
19.1 基本概念 495
19.2 使用System.Threading進行異步編程 497
19.2.1 耗時任務 497
19.2.2 最簡單的異步編程 497
19.2.3 獲得執行結果 498
19.2.4 實現迴調函數獲得執行結果 499
19.2.5 綫程統一取消模型 500
19.2.6 總結 504
19.3 基於委托的異步編程模型 505
19.3.1 APM的設計規範 505
19.3.2 獲得異步委托的執行結果 506
19.3.3 System.IAsyncResult接口 507
19.3.4 通過迴調的方式獲得異步委托的執行結果 508
19.3.5 使用綫程統一取消模型進行取消 509
19.3.6 捕獲異步編程的異常 511
19.3.7 GUI的綫程處理模型 512
19.3.8 GUI中使用委托進行異步—Control.Begin-Invoke原理 513
19.3.9 GUI中使用委托進行異步—WinForm程序示例 515
19.3.10 總結 517
19.4 基於事件的異步編程模式 518
19.4.1 EAP的設計規範 518
19.4.2 BackgroundWorker類簡介 519
19.4.3 GUI中使用EAP進行異步—WPF程序示例 521
19.4.4 總結 525
19.5 我們需要這麼多異步編程的方法嗎 525
19.6 本章小結 525
19.7 思考題 526
第20章 任務並行庫 527
20.1 任務並行庫 527
20.2 使用任務進行異步編程 528
20.2.1 新建任務 528
20.2.2 任務的狀態 529
20.2.3 任務調度器 530
20.2.4 任務工廠 531
20.3 獲得任務的執行結果 532
20.3.1 等待任務完成 532
20.3.2 任務連接作為迴調函數 533
20.3.3 使用過去的方式 539
20.4 任務的異常處理 539
20.4.1 父子任務中的異常處理(附加子任務) 541
20.4.2 父子任務中的異常處理(分離子任務) 541
20.5 任務的取消 544
20.5.1 直接退齣任務 544
20.5.2 利用ThrowIfCancellation-Requested方法545
20.5.3 任務取消的異常處理 545
20.5.4 任務異常處理:總結 548
20.6 在WPF中使用任務 549
20.7 並行編程與PLINQ 552
20.8 Parallel類 553
20.8.1 Parallel.Invoke與任務並行 554
20.8.2 Parallel.For/ForEach與數據並行 555
20.8.3 收集任務的執行結果 558
20.8.4 指定最大並行度 558
20.8.5 在Parallel類中捕捉異常 559
20.8.6 使用ParallelOption取消並行任務 560
20.8.7 使用ParallelLoopState退齣For/ForEach循環 562
20.8.8 Parallel方法的取消與異常處理總結 563
20.9 PLINQ 564
20.9.1 指定執行模式 566
20.9.2 指定並行度 567
20.9.3 PLINQ與排序 567
20.9.4 PLINQ的數據分區策略 568
20.9.5 PLINQ的輸齣端與結果收集策略 571
20.9.6 使用Aggregate的並行版本進行計算 572
20.9.7 取消PLINQ查詢 572
20.9.8 在PLINQ中捕捉異常 573
20.9.9 總結:是否需要使用PLINQ 574
20.10 Lazy和延遲初始化 574
20.11 本章小結 576
20.12 思考題 576
第21章 .NET 4.5異步編程實例 577
21.1 初識async/await 577
21.1.1 異步方法的執行流程 579
21.1.2 異步方法的異常處理 582
21.1.3 異步方法的取消 584
21.1.4 調用方法獲得結果的幾種方式 585
21.1.5 async和await總結 587
21.2 瞭解async/await的原理 588
21.2.1 示例程序 588
21.2.2 使用ILSpy反編譯 589
21.2.3 狀態機結構 589
21.2.4 骨架方法 594
21.2.5 異常處理 595
21.3 GUI:使用async和await關鍵字進行異步操作 595
21.3.1 異步操作的基本模型 596
21.3.2 使用WhenAll等待一組任務完成 597
21.3.3 使用WhenAny等待任意一個任務完成 598
21.3.4 任務完成時的處理 599
21.4 可等待模式 600
21.4.1 定義 600
21.4.2 await anything 601
21.5 本章小結 603
21.6 思考題 604
後記 605
附錄 程序員麵試流程概覽 606
· · · · · · (
收起)