1:用属性来访问类的私有成员
Always use properties instead of accessible data members.
2:为常量优先选择readonly而不是const。
Prefer readonly to const.
const常量仅限于几个基本类型,编译时绑定;readonly常量在运行时绑定。
3:优先选择is或者as操作符而不是做强制类型转换.
Prefer the is or as operators to casts.
4:使用Conditional属性来代替IF/ENDIF程序块。
Use Conditional Attributes Instead of #if。
5: 始终提供一个有意义的ToString函数.
Always Provide ToString().
默认继承object的方法ToString()返回的结果是GetType()后转换成String.
6:区别值类型数据和引用类型数据.
Distinguish Between Value Types and Reference Types.
把底层面的数据用值类型来处理,而包含复杂操作,需要进行扩展的数据用引用类型来处理。
7: 将值类型尽可能实现为具有常量性和原子性的类型.
Prefer Immutable Atomic Value Types.
两种方法:1.所有成员加上readonly标示,只在构造函数中被修改;2.删除属性set部分。
在实现不可变的原子值类型(若其中包括引用类型分支)时,在进行成员赋值时,防止浅copy。
8: 确保0为值类型的有效状态.
Ensure That 0 Is a Valid State for Value Types
数值类型的默认值为0,但0在enum中可能无意义。
9: 理解4个相等判断之间的关系.
Understand the Relationships Among ReferenceEquals(),static Equals(),instance Equals() and operator==.
ReferenceEquals():判断两个引用类型对象是否指向同一个地址;
static Equals() :把比较的职责委交给了一个正在比较的类型(第一个参数的类型);
instance Equals():类型重载函数。不要在值类型中重载此运算符(boxing开销);
operator== :类型重载函数。不要在引用类型中重载此运算符;
10:理解GetHashCode()方法的缺陷.
Understand the Pitfalls of GetHashCode().
GetHashCode()的目的是产生一个Key,为了方便在HashTable或者Dictionary中的检索。引用类型的GetHashCode()其实就是返回当前引用标记(一般都是正确的,不必override);值类型自带的GetHashCode()是以其第一个成员的GetHashCode值作为其的返回值(一般都是不正确的)。
不建议使用值类型对象的GetHashCode函数返回值来作为HashTable对象的Key;
引用类型是可以使用的,但是要注意如果重写了Equals函数,一定要重写GetHashCode函数来达到一致;
重写此函数时注意:
1.不管是值类型还是引用类型,要保证产生HashCode的成员不能被修改;
2. 对于产生HashCode的成员修改,要以产生新对象进行处理,同时要在使用端作相应的修改,即先删除旧的在添加新的。
11:优先采用foreach循环语句.
Prefer foreach Loops.
foreach能为迭代非0下限的数组、多维数组生成正确的代码。但foreach有两个限制:1.不能修改枚举成员;2.不要对集合进行删除操作。