第Ⅰ部分 C#语言 3
第1章 C#的起源 3
1.1 C#的族谱 3
1.1.1 C语言:现代编程的开端 3
1.1.2 OOP和C++语言的诞生 4
1.1.3 Internet和Java的出现 4
1.1.4 C#的诞生 5
1.1.5 C#的发展 6
1.2 C#如何与.NET Framework相关 7
1.3 公共语言运行时的工作原理 7
1.4 托管和非托管代码 8
第2章 C#概述 9
2.1 面向对象编程 9
2.1.1 封装 10
2.1.2 多态 10
2.1.3 继承 11
2.2 简单示例一 11
2.2.1 C#命令行编译器csc.exe 11
2.2.2 使用Visual Studio IDE 12
2.2.3 逐行分析第一个示例程序 16
2.3 处理语法错误 18
2.4 改写示例一 19
2.5 简单示例二 19
2.6 另一种数据类型 21
2.7 两种控制语句 23
2.7.1 if语句 23
2.7.2 for循环 25
2.8 代码块 26
2.9 分号、定位和缩进 27
2.10 C#语言的关键字 28
2.11 标识符 29
2.12 .NET Framework类库 30
第3章 数据类型、字面量和变量 31
3.1 数据类型的重要性 31
3.2 C#的值类型 31
3.3 整数类型 32
3.4 浮点类型 34
3.5 decimal类型 36
3.6 字符类型 37
3.7 布尔类型 38
3.8 自定义输出格式 39
3.9 字面量 42
3.9.1 十六进制字面量 42
3.9.2 字符转义序列 43
3.9.3 字符串字面量 43
3.10 变量 45
3.10.1 初始化变量 45
3.10.2 动态初始化变量 46
3.10.3 隐式类型的变量 46
3.11 变量的作用域和生命周期 48
3.12 类型转换和强制类型转换 50
3.12.1 自动类型转换 50
3.12.2 强制转换不兼容的类型 51
3.13 表达式中的类型转换 54
第4章 运算符 59
4.1 算术运算符 59
4.2 关系和逻辑运算符 63
4.3 赋值运算符 67
4.4 按位运算符 69
4.4.1 按位与、或、异或和一元取反运算符 69
4.4.2 移位运算符 75
4.4.3 按位复合赋值 78
4.5 问号(?)运算符 78
4.6 空格和圆括号 79
4.7 运算符优先级 80
第5章 程序控制语句 81
5.1 if语句 81
5.1.1 if语句嵌套 82
5.1.2 if-else-if阶梯结构 83
5.2 switch语句 84
5.3 for循环 88
5.4 while循环 96
5.5 do-while循环 97
5.6 foreach循环 98
5.7 使用break语句退出循环 98
5.8 使用continue语句 101
5.9 goto语句 102
第6章 类和对象 105
6.1 类的基础知识 105
6.1.1 类的通用形式 105
6.1.2 定义类 106
6.2 创建对象的方式 110
6.3 引用类型的变量和赋值 111
6.4 方法 111
6.4.1 给Building类添加方法 112
6.4.2 从方法返回 114
6.4.3 返回值 115
6.4.4 使用参数 117
6.4.5 给Building类添加带参数的方法 119
6.4.6 避免产生不可到达的代码 121
6.5 构造函数 121
6.5.1 带参数的构造函数 122
6.5.2 给Building类添加构造函数 123
6.6 new运算符 124
6.7 垃圾回收和析构函数 125
6.8 this关键字 127
第7章 数组和字符串 131
7.1 数组 131
7.2 多维数组 135
7.2.1 二维数组 135
7.2.2 三维或更多维的数组 137
7.2.3 初始化多维数组 137
7.3 交错数组 139
7.4 数组引用赋值 141
7.5 Length属性 142
7.6 隐式类型的数组 145
7.7 foreach循环 147
7.8 字符串 150
7.8.1 构造string类型对象 151
7.8.2 操作字符串 151
7.8.3 字符串数组 155
7.8.4 字符串是不可改变的 157
7.8.5 在switch语句中使用字符串 158
第8章 方法和类 159
8.1 控制对类成员的访问 159
8.1.1 C#的访问修饰符 159
8.1.2 公有访问和私有访问的应用 161
8.1.3 访问控制:案例研究 161
8.2 给方法传递引用 166
8.3 使用ref和out参数 170
8.3.1 使用ref关键字 170
8.3.2 使用out关键字 172
8.3.3 对引用参数使用ref和out关键字 174
8.4 使用数量可变的参数 176
8.5 返回对象 178
8.6 方法重载 182
8.7 构造函数重载 187
8.8 对象初始化器 193
8.9 可选实参 194
8.9.1 可选实参与重载 196
8.9.2 可选实参与多义性 196
8.9.3 可选实参的实际示例 197
8.10 命名实参 198
8.11 Main()方法 200
8.11.1 从Main()方法返回值 200
8.11.2 给Main()方法传递参数 200
8.12 递归 202
8.13 理解static关键字 205
8.14 static类 210
第9章 运算符重载 213
9.1 运算符重载基础 213
9.1.1 重载二元运算符 214
9.1.2 重载一元运算符 216
9.2 处理针对C#内置类型的运算 220
9.3 重载关系运算符 225
9.4 重载true和false 227
9.5 重载逻辑运算符 229
9.5.1 重载逻辑运算符的简单方式 229
9.5.2 使用短路运算符 231
9.6 转换运算符 236
9.7 运算符重载的注意事项 240
9.8 运算符重载的另一个示例 241
第10章 索引器和属性 245
10.1 索引器 245
10.1.1 创建一维索引器 245
10.1.2 索引器重载 249
10.1.3 索引器不需要底层的数组 251
10.1.4 多维索引器 252
10.2 属性 255
10.2.1 自动实现属性 260
10.2.2 对属性使用对象初始化器 260
10.2.3 属性限制 261
10.3 对存取器使用访问修饰符 261
10.4 使用索引器和属性 264
第11章 继承 271
11.1 继承基础 271
11.2 成员访问和继承 274
11.3 构造函数和继承 278
11.4 继承和名称隐藏 285
11.5 创建多层的层次结构 288
11.6 构造函数的调用 291
11.7 基类引用和派生对象 292
11.8 虚方法和重写 296
11.8.1 重写方法的原因 300
11.8.2 应用虚方法 300
11.9 使用抽象类 304
11.10 使用sealed关键字阻止继承 308
11.11 object类 308
11.11.1 装箱和拆箱 310
11.11.2 object类型是否是通用数据类型 312
第12章 接口、结构和枚举 315
12.1 接口 315
12.2 使用接口类型的引用 320
12.3 接口属性 322
12.4 接口索引器 324
12.5 接口的继承 326
12.6 接口继承引起的名称隐藏 327
12.7 显式实现 327
12.8 在接口和抽象类之间选择 330
12.9 .NET标准接口 330
12.10 结构 330
12.11 枚举 335
12.11.1 初始化枚举 337
12.11.2 指定枚举的基本类型 338
12.11.3 使用枚举 338
第13章 异常处理 341
13.1 SystemException类 341
13.2 异常处理的基础 341
13.2.1 使用try和catch关键字 342
13.2.2 一个简单的异常示例 342
13.2.3 另一个异常示例 344
13.3 未捕获异常的后果 345
13.4 使用异常可以妥善地处理错误 347
13.5 使用多条catch子句 347
13.6 捕获所有的异常 348
13.7 嵌套try块 350
13.8 抛出异常 351
13.9 finally语句 353
13.10 进一步分析Exception类 355
13.11 派生异常类 358
13.12 捕获派生类异常 361
13.13 checked和unchecked关键字 363
第14章 I/O系统 367
14.1 C#的I/O依赖于数据流 367
14.1.1 字节数据流和字符数据流 367
14.1.2 预定义数据流 367
14.2 数据流类 368
14.2.1 Stream类 368
14.2.2 字节数据流类 369
14.2.3 字符数据流包装类 369
14.2.4 二进制数据流 371
14.3 控制台I/O 371
14.3.1 读取控制台输入 371
14.3.2 使用ReadKey()方法 373
14.3.3 写入控制台输出 375
14.4 文件数据流和面向字节的文件I/O操作 376
14.4.1 打开和关闭文件 376
14.4.2 使用FileStream类从文件中读取字节 378
14.4.3 写入文件 380
14.4.4 使用FileStream类复制文件 382
14.5 基于字符的文件I/O操作 383
14.5.1 使用StreamWriter类 383
14.5.2 使用StreamReader类 385
14.6 重定向标准数据流 386
14.7 读取和写入二进制数据 388
14.7.1 BinaryWriter类 388
14.7.2 BinaryReader类 389
14.7.3 二进制I/O操作的程序示例 390
14.8 随机访问文件 395
14.9 使用MemoryStream类 396
14.10 StringReader和StringWriter类 399
14.11 File类 400
14.11.1 使用Copy()方法复制文件 400
14.11.2 使用Exists()和GetLastAccessTime()方法 401
14.12 将数值型字符串转换为内部表示格式 402
第15章 委托、事件和Lambda表达式 407
15.1 委托 407
15.1.1 委托的方法组转换 410
15.1.2 使用实例方法作为委托 410
15.1.3 多播委托 412
15.1.4 协变和逆变 414
15.1.5 System.Delegate类 416
15.1.6 使用委托的原因 416
15.2 匿名函数 416
15.3 匿名方法 416
15.3.1 给匿名方法传递参数 417
15.3.2 从匿名方法中返回值 418
15.3.3 在匿名方法中使用外部变量 419
15.4 Lambda表达式 421
15.4.1 Lambda运算符 421
15.4.2 表达式Lambda 422
15.4.3 语句Lambda 424
15.5 事件 427
15.5.1 多播委托事件的示例 428
15.5.2 作为事件处理程序的实例方法和static方法的区别 430
15.5.3 使用事件存取器 432
15.5.4 事件的其他功能 437
15.6 对事件使用匿名方法和Lambda表达式 437
15.7 .NET事件的指导原则 438
15.8 事件的应用:案例研究 441
第16章 名称空间、预处理器和程序集 445
16.1 名称空间 445
16.1.1 名称空间的声明 445
16.1.2 名称空间可以避免名称冲突 448
16.1.3 using指令 449
16.1.4 using指令的另一种形式 451
16.1.5 名称空间的合成 453
16.1.6 嵌套名称空间 454
16.1.7 全局名称空间 456
16.1.8 使用名称空间别名限定符(∷) 456
16.2 预处理器 460
16.2.1 #define 460
16.2.2 #if和#endif 461
16.2.3 #else和#elif 462
16.2.4 #undef 464
16.2.5 #error 464
16.2.6 #warning 465
16.2.7 #line 465
16.2.8 #region和#endregion 465
16.2.9 #pragma 465
16.3 程序集和internal访问修饰符 466
第17章 运行时类型标识、反射和特性 469
17.1 运行时类型标识 469
17.1.1 使用is运算符测试类型 469
17.1.2 使用as运算符 470
17.1.3 使用typeof运算符 472
17.2 反射 473
17.3 使用反射 475
17.3.1 获取方法的相关信息 475
17.3.2 GetMethods()方法的另一种形式 478
17.3.3 使用反射调用方法 479
17.3.4 获取Type对象的构造函数 481
17.3.5 从程序集获得类型 486
17.3.6 全自动类型查询 491
17.4 特性 493
17.4.1 特性基础 494
17.4.2 位置形参和命名形参 497
17.5 3个内置特性 501
17.5.1 AttributeUsage特性 501
17.5.2 Conditional特性 501
17.5.3 Obsolete特性 502
第18章 泛型 505
18.1 泛型的概念 505
18.2 一个简单的泛型示例 506
18.2.1 泛型类型基于类型实参而有所不同 509
18.2.2 泛型如何实现类型安全 509
18.3 使用两个类型形参的泛型类 512
18.4 泛型类的通用形式 513
18.5 类型约束 513
18.5.1 基类约束 514
18.5.2 接口约束 522
18.5.3 new()构造函数约束 525
18.5.4 引用类型约束和值类型约束 527
18.5.5 使用约束建立两个类型形参之间的关系 529
18.5.6 使用多个约束 530
18.6 创建类型形参的默认值 531
18.7 泛型结构 533
18.8 创建泛型方法 534
18.8.1 调用泛型方法时显式地指定类型实参 536
18.8.2 为泛型方法指定约束 536
18.9 泛型委托 537
18.10 泛型接口 538
18.11 比较同一个类型形参的实例 542
18.12 泛型类的层次结构 546
18.12.1 使用泛型基类 546
18.12.2 泛型派生类 548
18.13 重写泛型类中的虚方法 549
18.14 重载使用类型形参的方法 550
18.15 泛型类型形参中的协变和逆变 552
18.15.1 在泛型接口中使用协变 552
18.15.2 在泛型接口中使用逆变 555
18.15.3 委托变体 558
18.16 泛型类型的实例化 560
18.17 使用泛型时的一些限制 561
18.18 泛型小结 561
第19章 LINQ 563
19.1 LINQ的基础知识 564
19.1.1 简单查询 564
19.1.2 查询可以多次执行 566
19.1.3 查询中的数据类型的关联方式 567
19.1.4 查询的通用形式 568
19.2 使用where子句筛选值 568
19.3 使用orderby子句排序结果 570
19.4 深入讨论select子句 573
19.5 使用嵌套的from子句 577
19.6 使用group子句分组结果 578
19.7 使用into子句创建延续 580
19.8 在查询中使用let子句创建变量 582
19.9 使用join子句连接两个序列 583
19.10 匿名类型 586
19.11 创建组连接 588
19.12 查询方法 590
19.12.1 基本查询方法 591
19.12.2 使用查询方法创建查询 592
19.12.3 查询语法与查询方法的对比 594
19.12.4 更多与查询相关的扩展方法 594
19.13 延期执行查询和立即执行查询 596
19.14 表达式树 597
19.15 扩展方法 599
19.16 PLINQ 601
第20章 不安全代码、指针、可空类型、dynamic类型和其他主题 603
20.1 不安全代码 603
20.1.1 指针的基础知识 604
20.1.2 使用unsafe关键字 605
20.1.3 使用fixed修饰符 606
20 1.4 通过指针访问结构成员 607
20.1.5 指针运算 607
20.1.6 指针的比较 609
20.1.7 指针和数组 609
20.1.8 指针和字符串 611
20.1.9 多重间接寻址 612
20.1.10 指针数组 613
20.1.11 sizeof 613
20.1.12 stackalloc 613
20.1.13 创建固定大小的缓冲区 614
20.2 可空类型 615
20.2.1 可空类型基础 616
20.2.2 表达式中的可空对象 617
20.2.3 “??”运算符 618
20.2.4 在可空对象上使用关系和逻辑运算符 619
20.3 部分类型 620
20.4 部分方法 621
20.5 使用dynamic关键字创建dynamic类型 622
20.6 COM互操作性 626
20.7 友元程序集 627
20.8 其他关键字 627
20.8.1 lock关键字 627
20.8.2 readonly关键字 628
20.8.3 const和volatile关键字 629
20.8.4 using语句 629
20.8.5 extern关键字 630
第Ⅱ部分 C#类库研究 637
第21章 研究System名称空间 637
21.1 System名称空间的成员 637
21.2 Math类 639
21.3 与内置值类型对应的.NET结构 644
21.3.1 整型结构 645
21.3.2 浮点类型结构 647
21.3.3 Decimal结构 650
21.3.4 Char结构 653
21.3.5 Boolean结构 658
21.4 Array类 659
21.4.1 排序和搜索数组 667
21.4.2 反转数组 670
21.4.3 复制数组 671
21.4.4 使用谓词 672
21.4.5 使用Action委托 673
21.5 BitConverter类 674
21.6 使用Random类产生随机数 676
21.7 内存管理和GC类 677
21.8 Object类 679
21.9 Tuple类 679
21.10 IComparable和IComparable〈T〉接口 679
21.11 IEquatable〈T〉接口 680
21.12 IConvertible接口 680
21.13 ICloneable接口 680
21.14 IFormatProvider和IFormattable接口 682
21.15 IObservable〈T〉和IObserver〈T〉接口 683
第22章 字符串和格式化 685
22.1 C#中的字符串 685
22.2 String类 685
22.2.1 字符串构造函数 686
22.2.2 String类的字段、索引器和属性 686
22.2.3 字符串运算符 687
22.2.4 字符串方法 687
22.2.5 填充和剪裁字符串 704
22.2.6 插入、删除和替换 706
22.2.7 改变字母大小写 707
22.2.8 使用Substring()方法 708
22.2.9 字符串扩展方法 708
22.3 格式化 708
22.3.1 格式化概述 709
22.3.2 数字格式说明符 709
22.3.3 理解实参编号 711
22.4 使用String.Format()和ToString()方法格式化数据 712
22.4.1 使用String.Format()方法格式化值 712
22.4.2 使用ToString()方法格式化数据 714
22.5 自定义数字格式 715
22.6 格式化日期和时间 719
22.6.1 自定义日期和时间格式 721
22.6.2 格式化时间间隔 723
22.7 格式化枚举 725
第23章 多线程编程第1部分 727
23.1 多线程基础 727
23.2 Thread类 728
23.2.1 创建和启动线程 729
23.2.2 一些简单的改进 731
23.2.3 创建多个线程 732
23.3 确定线程结束的时间 734
23.4 为线程传递实参 737
23.5 IsBackground属性 739
23.6 线程优先级 739
23.7 同步 741
23.7.1 实现同步的另一种方式 745
23.7.2 Monitor类和lock关键字的关系 746
23.8 使用Wait()、Pulse()和PulseAll()方法实现线程通信 747
23.9 死锁和竞争条件 751
23.10 使用MethodImplAttribute特性 751
23.11 使用互斥锁和信号量 753
23.11.1 互斥锁 753
23.11.2 信号量 757
23.12 使用事件 760
23.13 Interlocked类 762
23.14 .NET 4.0添加的同步类 764
23.15 通过Abort()方法终止线程 764
23.15.1 Abort()方法的另一种形式 766
23.15.2 取消Abort()方法 767
23.16 挂起和恢复线程 769
23.17 判断线程的状态 769
23.18 使用主线程 769
23.19 .NET 4.0添加的其他多线程功能 771
23.20 多线程提示 771
23.21 启动独立的任务 771
第24章 多线程编程第2部分:研究任务并行库和PLINQ 773
24.1 并行编程的两种方式 773
24.2 Task类 774
24.2.1 创建任务 774
24.2.2 使用任务ID 777
24.3 使用等待方法 778
24.4 使用TaskFactory类启动任务 781
24.5 将Lambda表达式用作任务 782
24.6 创建任务延续 783
24.7 从任务返回值 785
24.8 取消任务和使用AggregateException异常 787
24.9 其他一些任务功能 790
24.10 Parallel类 790
24.10.1 通过Invoke()方法并行化任务 791
24.10.2 使用For()方法 793
24.10.3 使用ForEach()方法 799
24.11 研究PLINQ 800
24.11.1 ParallelEnumerable类 800
24.11.2 使用AsParallel()方法并行化查询 801
24.11.3 使用AsOrdered()方法 802
24.11.4 取消并行查询方法 802
24.11.5 其他PLINQ功能 804
24.11.6 有关PLINQ的注意事项 804
第25章 集合、枚举器和迭代器 805
25.1 集合概述 805
25.2 非泛型集合 806
25.2.1 非泛型接口 806
25.2.2 DictionaryEntry结构 811
25.2.3 非泛型集合类 811
25.3 使用BitArray类存储位 827
25.4 专用集合 829
25.5 泛型集合 830
25.5.1 泛型接口 830
25.5.2 KeyValuePair〈TKey,TValue〉结构 834
25.5.3 泛型集合类 834
25.6 并行集合 853
25.7 在集合中存储用户自定义的类 857
25.8 实现IComparable接口 860
25.8.1 为非泛型集合实现IComparable接口 860
25.8.2 为泛型集合实现IComparable〈T〉接口 861
25.9 使用IComparer接口 863
25.9.1 使用非泛型的IComparer接口 863
25.9.2 使用泛型的IComparer〈T〉接口 865
25.10 使用StringComparer类 866
25.11 通过枚举器访问集合 866
25.11.1 使用枚举器 867
25.11.2 使用IDictionary Enumerator接口 868
25.12 实现IEnumerable和IEnumerator接口 869
25.13 使用迭代器 871
25.13.1 停用迭代器 873
25.13.2 使用多条yield指令 874
25.13.3 创建命名迭代器 874
25.13.4 创建泛型迭代器 876
25.14 集合初始化器 877
第26章 使用System.Net名称空间通过Internet联网 879
26.1 System.Net名称空间的成员 879
26.2 统一资源标识符 881
26.3 Internet访问基础 881
26.3.1 WebRequest类 882
26.3.2 WebResponse类 884
26.3.3 HttpWebRequest和HttpWebResponse类 885
26.3.4 第一个简单的示例 885
26.4 处理网络错误 887
26.4.1 Create()方法产生的异常 887
26.4.2 GetResponse()方法产生的异常 887
26.4.3 GetResponseStream()方法产生的异常 888
26.4.4 使用异常处理 888
26.5 Uri类 890
26.6 访问附加的HTTP响应信息 891
26.6.1 访问报头 892
26.6.2 访问cookie 893
26.6.3 使用LastModified属性 894
26.7 MiniCrawler:案例研究 895
26.8 使用WebClient类 898
附录A 文档注释快速参考 903
A.1 XML注释标记 903
A.2 编译文档注释 904
A.3 XML文档示例 905