读了《C#高效编程--改进C#代码的50个行之有效的办法》,在此将书中的编程建议做简单记录。我读的这本的书的第二版,是基于.NET4.0的。
第1章 C#语言习惯
条目1 使用属性(Property)而不是可访问的数据成员
- 只有属性才能应用数据绑定功能
- 属性使用方法实现,可以进行数据验证,多线程支持
- 属性可以定义为抽象的,比如用在接口中,
public interface INameValuePair<T> { string Name { get; } T Value { get; set; } }
- 属性可以为读写行为定义不同访问级别。
- 通过索引器属性来暴露可索引的类项目
条目2 用运行时常量(readonly)而不是编译期常量(const)
- const常量在编译时替换,readonly常量在运行时求值
- const常量只能是基本类型(整数,浮点数),枚举及字符串,readonly常量可以是任何类型,在构造函数中对其进行初始化
- 对于跨程序集引用的常量,readonly常量是被引用为一个变量,而const变量被引用的是一个值,如果局部的更新常量所在程序集,那么其它程序集如果引用了const常量,则需要重新编译才能反应出其值的变化,而readonly常量则不需要。
条目3 推荐使用is或as操作符而不是强制类型转换
可以避免转型失败的异常处理,方便的进行类型的检查与转换
条目4 使用Conditional特性而不是#if条件编译
- #if定义的代码在指定条件不成立的情况下依然会被编译到程序集中,而Conditional特性不会
- Conditional特性应用在方法层面,被应用的方法不能有返回值,同时最好也没有参数,如果指定的条件不成立,那么对于参数进行改的变的操作没有进行,可以引起难以调试的Bug
- 多个编译条件或的关系可用Conditional特性,而与的关系只能用#if的方式
条目5 为类型提供ToString()方法
以可读的方式输出类的主要信息,也可通过实现IFormattable接口等方法,以格式化的方法输出类的主要内容。
条目6 理解几个等同性判断之间的关系
条目7 理解GetHashCode()的陷阱
条目8 推荐使用查询语法而不是循环
条目9 避免在API中使用转换操作符
条目10 使用可选参数减少方法重载的数量
条目11 理解短小方法的优势
很多编程规范中都从代码的可读性,易维护性的角度提出过方法应简短的建议,在.NET程序中,CLR调用JIT按函数粒度逐一将IL翻译成机器码,没有被调用的方法不会被JIT调用,这样可以提高程序启动速度。
第2章 .NET资源管理
条目12 推荐使用成员初始化器而不是赋值语句
条目13 正确地初始化静态成员变量
条目14 尽量减少重复的初始化逻辑
条目15 使用using和try/finally清理资源
条目16 避免创建非必要的对象
- 如果局部变量使用频率较高,应该将其提升为成员变量,减少频繁创建和销毁的开销。
- 提供一个类存放某个常用实例对象,如果GDI+中常用画刷的实现模式
- 大量的拼接字符串操作应用StringBuilder类
条目17 实现标准的销毁模式
- 微软定义的可处置对象的处置模式
public class MyResourceWrapper : IDisposable{ private bool disposed = false; protected virtual void Dispose(bool disposing) { //用true表示对象用户触发了清理过程 CleanUp(true); //跳过终结(析构) GC.SuppressFinalize(this); } private void CleanUp(bool disposing) { //防止重复清理 if (!this.disposed) { if (disposing) { //释放托管资源 } //释放非托管资源 } disposed = true; } /// <summary> /// 没有显示调用Dispose()时,GC会调用终结函数清理非托管资源 /// </summary> ~MyResourceWrapper() { CleanUp(false); } }
条目18 区分值类型和引用类型
- 结构用来存放数据,类用来定义行为
- 一个元素的值类型,初始化空间时只需要要一次操作,而引用类型需要101次,首先是引用所占空间,然后是每个元素的初始化
- 判断是否应用结构的标准:1)类型的主要职责是存储数据;2)类型所有公有接口都是由访问其数据成员的属性定义的吗?3)该类型永远不会有派生类?4)该类型永远不需要支持多态?
条目19 保证0为值类型的有效状态
条目20 保证值类型的常量性和原子性