• 编写高质量代码:改善C#程序的157个建议


    目录

    前 言
    第一部分 语言篇
    第1章 基本语言要素 / 2
    建议1:正确操作字符串 / 2
    建议2:使用默认转型方法 / 6
    建议3:区别对待强制转型与as和is / 9
    建议4:TryParse比Parse好 / 12
    建议5:使用int?来确保值类型也可以为null / 15
    建议6:区别readonly和const的使用方法 / 16
    建议7:将0值作为枚举的默认值 / 19
    建议8:避免给枚举类型的元素提供显式的值 / 20
    建议9:习惯重载运算符 / 22
    建议10:创建对象时需要考虑是否实现比较器 / 23
    建议11:区别对待==和Equals / 27
    建议12:重写Equals时也要重写GetHashCode / 29
    建议13:为类型输出格式化字符串 / 32
    建议14:正确实现浅拷贝和深拷贝 / 36
    建议15:使用dynamic来简化反射实现 / 40


    第2章 集合和LINQ / 43
    建议16:元素数量可变的情况下不应使用数组 / 43
    建议17:多数情况下使用foreach进行循环遍历 / 45
    建议18:foreach不能代替for / 51
    建议19:使用更有效的对象和集合初始化 / 53
    建议20:使用泛型集合代替非泛型集合 / 54
    建议21:选择正确的集合 / 57
    建议22:确保集合的线程安全 / 61
    建议23:避免将List作为自定义集合类的基类 / 64
    建议24:迭代器应该是只读的 / 67
    建议25:谨慎集合属性的可写操作 / 68
    建议26:使用匿名类型存储LINQ查询结果 / 70
    建议27:在查询中使用Lambda表达式 / 73
    建议28:理解延迟求值和主动求值之间的区别 / 75
    建议29:区别LINQ查询中的IEnumerable和IQueryable / 78
    建议30:使用LINQ取代集合中的比较器和迭代器 / 80
    建议31:在LINQ查询中避免不必要的迭代 / 83


    第3章 泛型、委托和事件 / 86
    建议32:总是优先考虑泛型 / 86
    建议33:避免在泛型类型中声明静态成员 / 88
    建议34:为泛型参数设定约束 / 90
    建议35:使用default为泛型类型变量指定初始值 / 92
    建议36:使用FCL中的委托声明 / 94
    建议37:使用Lambda表达式代替方法和匿名方法 / 96
    建议38:小心闭包中的陷阱 / 99
    建议39:了解委托的实质 / 103
    建议40:使用event关键字为委托施加保护 / 106
    建议41:实现标准的事件模型 / 108
    建议42:使用泛型参数兼容泛型接口的不可变性 / 109
    建议43:让接口中的泛型参数支持协变 / 111
    建议44:理解委托中的协变 / 112
    建议45:为泛型类型参数指定逆变 / 114


    第4章 资源管理和序列化 / 116
    建议46:显式释放资源需继承接口IDisposable / 116
    建议47:即使提供了显式释放方法,也应该在终结器中提供隐式清理 / 119
    建议48:Dispose方法应允许被多次调用 / 120
    建议49:在Dispose模式中应提取一个受保护的虚方法 / 121
    建议50:在Dispose模式中应区别对待托管资源和非托管资源 / 123
    建议51:具有可释放字段的类型或拥有本机资源的类型应该是可释放的 / 124
    建议52:及时释放资源 / 125
    建议53:必要时应将不再使用的对象引用赋值为null / 127
    建议54:为无用字段标注不可序列化 / 131
    建议55:利用定制特性减少可序列化的字段 / 136
    建议56:使用继承ISerializable接口更灵活地控制序列化过程 / 137
    建议57:实现ISerializable的子类型应负责父类的序列化 / 140


    第5章 异常与自定义异常 / 144
    建议58:用抛出异常代替返回错误代码 / 144
    建议59:不要在不恰当的场合下引发异常 / 147
    建议60:重新引发异常时使用Inner Exception / 150
    建议61:避免在finally内撰写无效代码 / 151
    建议62:避免嵌套异常 / 157
    建议63:避免“吃掉”异常 / 160
    建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内 / 161
    建议65:总是处理未捕获的异常 / 162
    建议66:正确捕获多线程中的异常 / 166
    建议67:慎用自定义异常 / 168
    建议68:从System.Exception或其他常见的基本异常中派生异常 / 170
    建议69:应使用finally避免资源泄漏 / 172
    建议70:避免在调用栈较低的位置记录异常 / 175


    第6章 异步、多线程、任务和并行 / 177
    建议71:区分异步和多线程应用场景 / 177
    建议72:在线程同步中使用信号量 / 180
    建议73:避免锁定不恰当的同步对象 / 184
    建议74:警惕线程的IsBackground / 188
    建议75:警惕线程不会立即启动 / 189
    建议76:警惕线程的优先级 / 191
    建议77:正确停止线程 / 193
    建议78:应避免线程数量过多 / 194
    建议79:使用ThreadPool或BackgroundWorker代替Thread / 196
    建议80:用Task代替ThreadPool / 198
    建议81:使用Parallel简化同步状态下Task的使用 / 202
    建议82:Parallel简化但不等同于Task默认行为 / 204
    建议83:小心Parallel中的陷阱 / 205
    建议84:使用PLINQ / 208
    建议85:Task中的异常处理 / 209
    建议86:Parallel中的异常处理 / 214
    建议87:区分WPF和WinForm的线程模型 / 216
    建议88:并行并不总是速度更快 / 220
    建议89:在并行方法体中谨慎使用锁 / 222


    第二部分 架构篇
    第7章 成员设计 / 226
    建议90:不要为抽象类提供公开的构造方法 / 226
    建议91:可见字段应该重构为属性 / 226
    建议92:谨慎将数组或集合作为属性 / 227
    建议93:构造方法应初始化主要属性和字段 / 228
    建议94:区别对待override和new / 229
    建议95:避免在构造方法中调用虚成员 / 235
    建议96:成员应优先考虑公开基类型或接口 / 236
    建议97:优先考虑将基类型或接口作为参数传递 / 237
    建议98:用params减少重复参数 / 237
    建议99:重写时不应使用子类参数 / 238
    建议100:静态方法和实例方法没有区别 / 239
    建议101:使用扩展方法,向现有类型“添加”方法 / 240


    第8章 类型设计 / 243
    建议102:区分接口和抽象类的应用场合 / 243
    建议103:区分组合和继承的应用场合 / 245
    建议104:用多态代替条件语句 / 248
    建议105:使用私有构造函数强化单例 / 251
    建议106:为静态类添加静态构造函数 / 253
    建议107:区分静态类和单例 / 255
    建议108:将类型标识为sealed / 255
    建议109:谨慎使用嵌套类 / 256
    建议110:用类来代替enum / 257
    建议111:避免双向耦合 / 260
    建议112:将现实世界中的对象抽象为类,将可复用对象圈起来就是命名空间 / 262


    第9章 安全性设计 / 264
    建议113:声明变量前考虑最大值 / 264
    建议114:MD5不再安全 / 265
    建议115:通过HASH来验证文件是否被篡改 / 268
    建议116:避免用非对称算法加密文件 / 269
    建议117:使用SSL确保通信中的数据安全 / 273
    建议118:使用SecureString保存密钥等机密字符串 / 284
    建议119:不要使用自己的加密算法 / 289
    建议120:为程序集指定强名称 / 289
    建议121:为应用程序设定运行权限 / 291


    第三部分 编码规范及习惯
    第10章 命名规范 / 296
    建议122:以.为命名空间命名 / 296
    建议123:程序集不必与命名空间同名 / 296
    建议124:考虑在命名空间中使用复数 / 297
    建议125:避免用FCL的类型名称命名自己的类型 / / 297
    建议126:用名词和名词组给类型命名 / 298
    建议127:用形容词组给接口命名 / 299
    建议128:考虑让派生类的名字以基类名字作为后缀 / 300
    建议129:泛型类型参数要以T作为前缀 / 300
    建议130:以复数命名枚举类型,以单数命名枚举元素 / 301
    建议131:用PascalCasing命名公开元素 / 302
    建议132:考虑用类名作为属性名 / 302
    建议133:用camelCasing命名私有字段和局部变量 / 303
    建议134:有条件地使用前缀 / 304
    建议135: 考虑使用肯定性的短语命名布尔属性 / 305
    建议136:优先使用后缀表示已有类型的新版本 / 306
    建议137:委托和事件类型应添加上级后缀 / 307
    建议138:事件和委托变量使用动词或形容词短语命名 / 308
    建议139:事件处理器命名采用组合方式 / 309


    第11章 代码整洁 / 311
    建议140:使用默认的访问修饰符 / 311
    建议141:不知道该不该用大括号时,就用 / 312
    建议142:总是提供有意义的命名 / 314
    建议143:方法抽象级别应在同一层次 / 315
    建议144:一个方法只做一件事 / 316
    建议145:避免过长的方法和过长的类 / 317
    建议146:只对外公布必要的操作 / 318
    建议147:重构多个相关属性为一个类 / 319
    建议148:不重复代码 / 320
    建议149:使用表驱动法避免过长的if和switch分支 / 321
    建议150:使用匿名方法、Lambda表达式代替方法 / 324
    建议151:使用事件访问器替换公开的事件成员变量 / 325
    建议152:最少,甚至是不要注释 / 326
    建议153:若抛出异常,则必须要注释 / 326


    第12章 规范开发行为 / 327
    建议154:不要过度设计,在敏捷中体会重构的乐趣 / 327
    建议155:随生产代码一起提交单元测试代码 / 336
    建议156:利用特性为应用程序提供多个版本 / 342
    建议157:从写第一个界面开始,就进行自动化测试 / 344

    ====

  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/EthanSun/p/3223071.html
Copyright © 2020-2023  润新知