C#语法相比其它语言比较独特的地方(三)
1.在C++中允许从一个case贯穿到另一个case标签
比如:
inta=1; switch(a) { case1: somestatements; case2; otherstatements; break; }
第一个case和第二个case之间可以没有break
而在C#中这个break不能省略.
3.as和is只会检测待转化类型的类型,而不会进行其它操作,所以只有当转化类型是目标类型或者目标类型的子类(当然如果目标类型是接口,并且待转化类型实现了该接口也可以)才能转换成功.
强制转化,会调用系统定义(比如float转化为int类型)或自己定义的转化函数(通过implicitoperator定义).
从常规的需求来看,大部分情况下,推荐使用as转换.
但要注意as不能用于valuetype.因为在转换不成功的时候返回null,而valuetype不能为
null.这时可以考虑用is.
objecto=1; inti=0; if(oisint) i=(int)o;
6.const是编译时常量
readonly是运行时常量
推荐使用staticreadonly代替const
const变量被硬编码进assembly,有版本问题.
C#只是用sealed替代了fianl,另外C#的派生类在默认情况下不会override基类方法,只有当基类方法用关键字virtual标志,并且子类显式用override标志方法时才会override.这样也有效地解决了版本问题.
7.delegate在本质上就是函数指针.
因为委托还引发了sun和MS的论战.
Anders早在Borland的时候就在Delphi中引入了delegate,后来跑到MS,弄J#的时候又添加进了delegate,Sun很不满意,说他们破坏了Java语言的特性.
到了C#,Anders终于可以名正言顺地添加delegate了.
-------------------------------
狗尾续貂(二)
1.internalprotected取的是internal和protected的并集,即在同一个Assembly或者不同
的Assembly内但是继承自该类都可以访问.
3..NETFrameWork采用了字符串缓冲池技术.
比如stringa="test";和stringb="test";a和b指向内存中的同一块区域.
另外C#中有几种判等方式,是否重写可参照如下规则:
publicstaticboolReferenceEquals(objectleft,objectright); publicstaticboolEquals(objectleft,objectright); publicvirtualboolEquals(objectright); publicstaticbooloperator==(MyClassleft,MyClassright);
上述四个方法override应该遵循如下规则:
1.前两个无论如何不要override
2.第三个和第四个在自定义类型是ValueType的时候要改写
3.当自定义类型是ReferenceType的时候,如果想改变RefrenceType默认的用对象标志判等的方式,可以改写第三个
4.当自定义类型是RefrenceType的时候,最好不要改写operator==.
下面分别给出上述规则的原因:
1.
A.ReferenceEquals()这个方法当且仅当两个变量指向同一对象的时候才相等,它的实现是比较对象标志(ObjectIdentity,任何对象在创建的时候都会生成一个OI),所以任何值类型用ReferenceEquals()比较所得到的结果都是false,即使跟自己比较也是,因为要装箱,装箱的结果肯定不是同一个对象.所以这个方法也就没有改写的必要.object的ReferenceEquals()是实现这种比较最好的方式.
B.Equals(objectleft,objectright)这个方法用于在不知道待比较的参数是何种类型的时候.那如何比较两个变量是否相等那?很简单,把比较相等的职责交给其中一个待比较变量的Equals方法,上述方法的实现大概如下所述:
publicstaticboolEquals(objectleft,objectright) { //Checkobjectidentity if(left==right) returntrue; //bothnullreferenceshandledabove if((left==null)||(right==null)) returnfalse; returnleft.Equals(right); }
之所以不要重写上述两个方法,是因为两者都很好的实现了各自的语意.
2.为什么是值的时候要重写第三个方法?
ValueType是所有值类型的基类,由于要实现值相等的语意,它重写了object的Equals方法,但是在不知道派生类变量和其类型的情况下,ValueType的Equals在实现的时候只能用反射来比较,这样的效率是很低的,所以任何自定义的值类型都要重写Equals,以避免用ValueType的默认实现带来的反射的效率损失.
3.object的实例Equals方法的默认实现跟ReferenceEqual一样,是通过比较对象标志来实现的,有些ReferenceType需要值相等的语意,比如string,这是就要改写实例Equals.
4..NetFrameWork期望所有的ReferenceType的operator==保留引用语意.
相等在语意上必须满足三点
1.自反a=a必须永远成立;
2.对称a=b则b=a;
3.传递a=b;b=c则a=c
publicclassFoo { publicoverrideboolEquals(objectright) { //1.判断待比较变量引用是否为空 if(right==null) returnfalse; //2.是否指向同一实例,如果是同一实例则必然相等. if(object.ReferenceEquals(this,right)) returntrue;
//3.判断类型是否相同 if(this.GetType()!=right.GetType()) returnfalse;
//4.比较内容 returnCompareFooMembers( this,rightasFoo); } }