第1章 基本的代码风格 1
1.1换行的讲究 1
寻找最佳的断行位置 2
每行只写一条语句 4
分行定义变量 4
1.2避免代码过于拥挤 5
使用空行分隔代码块 5
使用空格降低代码密度 8
1.3如何缩进 10
嵌套或包含关系引起的缩进 11
因换行而产生的缩进 14
使用空格还是Tab键 15
1.4大括号 15
大括号的位置 16
空的大括号结构 17
仅包含单个语句的结构体 19
1.5保持项目文件的条理性 21
解决方案的结构呼应 21
代码文件的结构 22
使用#region标记来隐藏细节 24
第2章 养成良好的注释习惯 25
2.1何时需要注释 25
解释代码的意图 26
对局部变量的说明 26
充当代码标题 27
指出例外情况 30
开发过程的提示 30
2.2注释的格式 31
单行注释 32
多行注释 33
2.3正确使用XML文档注释 34
结构与类的XML文档注释 36
属性的XML文档注释 37
方法的XML文档注释 38
构造函数的XML文档注释 39
事件的XML文档注释 40
枚举类型的XML文档注释 41
泛型的XML文档注释 42
其他标记 43
第3章 一般命名规范 45
3.1 选用合适的名称 45
使用字符的限制 46
使用含义明确的英语 47
3.2大小写规则 49
Pascal规则 49
Camel规则 49
首字母缩写词与简写词 50
应在何时使用何种大小写规则 52
3.3考虑跨语言编程 54
不要通过大小写区分标识符 54
避免与其他语言的关键字重复 55
避免使用特定语言的术语 55
3.4命名一致与冲突 57
大小写无关原则 57
对基类型的命名暗示 58
对参数与属性的关系暗示 60
属性名称与自身类型同名 62
与命名空间相关的命名冲突 63
3.5匈牙利命名法 65
匈牙利命名法的弊端 66
考虑为控件应用匈牙利命名法 67
第4章 处理数据 69
4.1关于数据类型 69
整数 69
浮点数 71
布尔类型 74
字符与字符串 74
4.2变量的使用 77
尽可能使用内置关键字 77
初始化一切变量 78
集中使用变量 79
4.3使用枚举 83
何时使用枚举 84
如何为枚举命名 87
关于枚举项 89
标记枚举 90
4.4魔数——以字面数值出现在代码中的常量 92
4.5复杂的表达式 93
运算符的副作用 94
简化表达式 95
第5章 分支结构 98
5.1使用if结构 98
“=”与“=”的问题 98
如何处理复杂的条件 100
5.2使用switch结构 103
break语句 103
使用default子句要注意的问题 105
5.3选择if还是switch? 107
5.4关于判断顺序的设计 109
先判断最有可能成立的条件 110
预防因条件短路而丢失操作 113
5.5慎用goto语句 114
第6章 循环结构 117
6.1使用for还是while 117
for和while的语义比较 117
简单的数值迭代——for和while的思维模式的差异 118
预知循环次数——微波炉加热的启示 121
集合迭代——独特的foreach结构 122
6.2循环变量的使用 123
循环变量的命名 123
循环变量的定义 124
避免循环变量的非常规应用 125
6.3提高循环效率 127
避免不必要的重复劳动 127
避免不必要的循环 127
第7章 如何使用函数 129
7.1为什么要使用函数 129
函数与方法 129
代码复用 130
隐藏细节——使用函数进行抽象 132
7.2函数重载 135
重载的语义——为调用者提供方便 135
保持核心代码唯一 139
7.3参数的设计 142
参数的命名 142
不要使用保留项 142
何时使用变长参数列表 143
何时使用ref参数和out参数 145
参数的顺序 146
重载函数的参数一致性体现 146
7.4参数检查的必要性 150
检查零值及空引用 150
检查枚举类型 151
防止数据被篡改 152
在何处检查合法性 153
7.5函数的出口——离开函数的三种方式 154
返回值的用法 155
离开函数的时机 156
第8章 结构与类 159
8.1结构与类的比较 159
值类型与引用类型 159
何时应当使用结构 160
何时应当使用类 160
8.2结构与类的命名 161
措辞 161
避免与命名空间冲突 161
不要使用“C”前缀 162
后缀的使用 162
8.3如何搭建一个典型的结构 164
找准核心数据 164
数据的表现形式 165
定义等价原则 166
实现基本运算 168
8.4如何真正面向对象 169
第9章 封装 175
9.1构造函数 175
构造函数的语义 175
何时使用静态构造方法 177
构造函数的参数及其初始化 178
9.2 Finalize函数 181
垃圾回收器 181
IDisposable接口——显式释放资源的方法 181
释放资源的一般范式 184
9.3何时应该使用字段 185
存储核心数据 186
维持中间结果 187
常量字段 188
9.4如何使用字段 189
字段的命名 189
访问控制 190
9.5何时应该使用属性 192
属性的语义 192
数据访问控制 193
需要的后续操作 194
简单的数据处理 194
预定义的对象实例 195
9.6如何使用属性 195
属性的命名 195
访问控制 198
提供合理的默认值 199
保持轻量级的操作 199
在属性中抛出异常 199
9.7何时应该使用方法 200
表示某种操作 200
耗时的任务——方法在形式上的暗示作用 201
有副作用的操作 202
返回不确定的值 203
返回数组或集合对象 203
9.8如何使用方法 205
方法的命名 206
检查传入的参数 206
9.9静态类型及成员 206
9.10嵌套类型及其适用场合 206
9.11可变类型的安全性 208
9.12使用程序集与命名空间 210
程序集的划分 210
为什么要使用命名空间 210
命名空间的命名 211
命名空间的管理 212
第10章 继承与多态 214
10.1如何利用类继承 214
自上而下逐步细化 214
自下而上逐步抽象 217
10.2继承限制 222
强制继承的抽象类型 222
密封类型 222
扩展方法——直接向已有类型添加功能 223
10.3关于接口 224
接口的语义 224
接口的命名 225
使用接口还是类继承 225
10.4何时应当显式实现接口 227
解决接口之间的命名冲突 227
提供强类型操作 228
隐藏仅用于通过接口访问的成员 229
10.5使用多态 230
何时应进行重写 230
应当重写哪个成员 230
保持参数名称一致 233
10.6运算符重载 233
可重载的运算符 233
符合运算符的本意 235
运算符的关联性 235
类型转换运算符的重载 236
第11章 泛型机制 237
11.1装箱与取消装箱 237
11.2何时使用泛型 238
11.3泛型的类型参数设计 239
类型参数的命名 239
使用类型参数的时机 241
第12章 事件与委托 244
12.1何为事件驱动模式 244
12.2如何响应事件 245
事件处理函数 246
代码的分配 248
事件侦听器的使用 250
12.3如何提供事件 255
何时应当提供事件 256
事件的命名 256
传递与事件相关的数据 257
用于事件的委托及其要遵守的约定 259
触发事件 260
12.4使用委托 261
何时使用委托 261
何时使用匿名方法 261
基类型与派生类型 263
第13章 集合类型 264
13.1系统内置集合类型 264
数组 264
列表 266
字典 266
其他类型 267
13.2选用适当的集合类型要考虑的几个方面 267
容量 267
进出次序 268
定位的问题——索引/键访问 268
元素结构 269
排序 271
13.3性能比较 272
13.4提供自己的集合类型 274
何时应提供集合类型 274
集合类型的命名 276
提供与内置集合类型一致的行为 276
索引器及其应遵守的规则 278
迭代器 279
第14章 LINQ查询 282
14.1提高LINQ查询的效率 282
查询语法和方法语法的区别 282
LINQ查询的创建、执行与性能 284
减少返回的数据量 285
14.2 LINQ中的错误处理——采用防御式编程 286
14.3 LINQ查询的相关机制 288
匿名类型 288
隐式类型的局部变量 289
Lambda表达式与匿名函数 290
第15章 异常 292
15.1处理异常时应遵守的规范 292
15.2抛出异常 296
异常的语义 296
不应使用异常的位置 298
控制异常 298
异常的重新抛出——重新包装时要注意的 300
15.3选用合适的异常类型 303
常见的异常类型 303
不应使用的异常类型 304
15.4异常提示信息 305
15.5设计自定义异常及应遵循的约定 305
第16章 全球化与本地化 309
16.1分离与特定区域相关的信息 309
16.2处理特定区域性的数据 312
区分区域性与界面区域性 312
在内部使用Unicode 312
文本的比较与排序 313
不要假定区域性的行为 315
16.3何时使用固定区域性 316
16.4用户界面应注意的细节 316
使用资源 317
术语 318
界面布局 318
歧义 320
组合文本 320
附录A: C#、 VB.NET、 J#关键字表 323
附录B:常用的异常类型 325