Effective C# Chapter1-Language Elements Item 1 使用属性取代公共成员变量 Item 2 优先考虑readonly而不是const Item3 使用is/as取代转换操作符来进行对象类型转换 Item 4 使用ConditionalAttribute 取代 #if Item 5 总是提供ToString()方法 Item 6 理解Value Types 和 Referance Types的差别 Item 7 Perfer Immutable Atomic Value Type Item 8 确保0(对象默认值,default(T)) 是一个有效状态(已定义状态) Item 9 理解比較关系的方法:ReferanceEquals(), static Equals(), instance Equals() 和 operator == Item 10 理解GetHashCode()里的陷阱 Item 11 优先使用foreach
《EffectiveC#》这本书讲了一些关于C#语言的使用技巧和经验. 该系列文章是备忘录和自己的一些见解.程序猿们最喜欢这类问题了,欢迎讨论~
菜单
Item 1 使用属性取代公共成员变量
Item 2 优先考虑readonly而不是const
Item 3 使用is/as取代转换操作符来进行对象类型转换
Item 4 使用ConditionalAttribute 取代 #if
Item 5 总是提供ToString()方法
Item 6 理解Value Types 和 Referance Types的差别
Item 7 Perfer Immutable Atomic Value Type
Item 8 确保0(对象默认值,default(T)) 是一个有效状态(已定义状态)
Item 9 理解比較关系的方法:ReferanceEquals(), static Equals(), instance Equals() 和 operator ==
Item 10 理解GetHashCode()里的陷阱
Item 11 优先使用foreach
这个是C++转C#程序猿最開始纠结的地方。
1、假设直接是public DataMember ,这肯定不正确,不管是C++还是C#,都须要进行封装。
特别的,在C#中,假设使用DataMember,会导致在跨Assembly使用时,假设该变量有所变化(比方默认值),全部用到该变量的Assembly都得重编译.
这在多DLL的项目里会变成一种灾难.
2、Porperty 和 Indexer 是C#里的概念和语言上的特性类型
那么C++的Access Methods 为什么也不要用了呢?由于Access Methods是C++里的东东; 对成员的訪问控制,使用Property会得到一些C#提供的编程便利,比方能够直接对一个Property应用某个[Attribute],而使用Access Methods则须要分别处理Get 和 Set, 实现起来更加繁琐;
很多其它的语言特性也是基于"Property"的,这个语言属性在反射相关的编码活动中能得到类型上的差别,而Access Methods是编码风格,C#不正确其在语言上直接给予支持。
3、性能没区别
JIT为Property实现的是inline property accessor,所以性能和DataMember等价.
总结:
总是使用属性来向外提供数据訪问的能力(ValueType可能会有特例,比方Vector3, Matrix44之类);
总是使用Indexer来向外提供数据的队列或定位的能力
数据成员所有是private的(或protected,个人看法);
Property和Indexer都不得有异常抛出;
Item 2 优先考虑readonly而不是const
1、C#语言里有两种版本号的常量:编译期常量(const)和执行期常量(readonly)
const在编译成IL的时候,会直接将常量解释成字面值,而readonly则解释成某种引用
2、const效率最高,可是有潜在风险
两者都有价值,const无性能开销,是最高效的,由于直接使用字面值常量来生成IL代码。
关于潜在风险,考虑例如以下一种情况:
程序集的A版本号公布,里面有个const 值为4,因为是DataMember(參考Item1 的理由1),使用该程序集的client全部用到的代码都被编译成4了.
数周后,程序集更新到B版本号,const的值改为5了. 不论什么没又一次编译的相关程序集里该const使用处的地方的值还是4.(被坑过的同学请举手)
3、readonly有一定程度的灵活性,当然也有少量的性能开销
自然,这样的引用会带来性能开销,只是也就是个inline的开销罢了.
Item3 使用is/as取代转换操作符来进行对象类型转换
Item 4 使用ConditionalAttribute 取代 #if
1、这个函数能够在不论什么地方调用,在编译Release的时候,这个函数和其调用代码就像根本不存在一样。
Item 5 总是提供ToString()方法
Item 6 理解Value Types 和 Referance Types的差别
Item 7 Perfer Immutable Atomic Value Type
strcut Address { public int ZipCode{get;set;} public string CityName{get;set;} }
struct Address { private int _zipCode; private string _cityName; public int ZipCode { get { return _zipCode; } } public string CityName { get { return _cityName; } } public Address(int zipCode, string cityName) { _zipCode = zipCode; _cityName = cityName; } public void Modify(int zipCode, string cityName) { _zipCode = zipCode; _cityName = cityName; } }
public Address Modify(int zipCode, string cityName) { return new Address(zipCode, cityName); }
能够看到,我们仅仅改了一个函数,Modify不再更改对象内部的属性,而是创建了一个新的Address实例返回出去了。那么这个类就是具有 Immutable和Atomic属性的ValueType。
Item 8 确保0(对象默认值,default(T)) 是一个有效状态(已定义状态)
Item 9 理解比較关系的方法:ReferanceEquals(), static Equals(), instance Equals() 和 operator ==
public static bool ReferanceEquals(object left,object right) public static bool Equals(object left,object right) public virtual bool Equals(object right) public static bool operator==(T left, T right)
so many 比較函数...刚从C++过来的人预计一下子就晕了吧。以下的4条分别解释上述4种比較函数的特点和差别。
public static bool Equals(object left,object right) { if(left == right) return true; if(left==null || right == null) return false; return left.Equals(right); }
能够看到,这个函数先调用==,再调用instance.Equals ,很的完备,是吧?这里是有陷阱的。