值得注意的几个地方
(一)类型转换的is,as
is返回true/false;as返回null/一个指针。
if (o is Employee)
{
Employee e=(Employee)o;
}
is的弊端:
(1)如果转换成功,编译的时候会出现Warning:给定表达式始终为所提供的类型.
(2)上述典型代码中,CLR对o的类型检查了两次(因为我们两次使用了o?)。
Employee e=o as Employee;
if(e!=null){}
(二)我们可以给使用的命名空间或者类型创建别名
using MySystem=System;
using MyWeb=System.Web;
(三)由于数据类型的频繁使用,编译器允许我们使用简化的类型代替他们。
例如:用int代替Int32.
C#规范声称"作为一种编码风格,使用简化的关键字应该优于使用完整的系统类型名称"。
Jeffery反对,理由:
·C#程序员经常讨论使用String,还是string.都一样,编译时候把string自动转换为String。
·long对应的是Int64,可是这个在其他语言中可能是Int16,Int32,long没有固定的标准,然而直接使用Int64更能说明long的真正数据类型.
·既然System.Convert提供了ToInt32,ToBoolean,ToSingle之类的方法,使得我们使用简化关键字的代码有些不自然:int
a=Convert.ToInt32(b);
(四)溢出检查
Byte b=100;
b=[checked][uchecked]((Byte)(b+200));//Exception:OverflowException
溢出检查代码块(不能对块中调用方法进行溢出检查)
[unchecked][checked]{
Byte b=100;
b=(Byte)(b+200);
}
(五)ValueType & ReferenceType
ValueType分配在椎栈(或者叫栈)上,不受垃圾收集器的控制。
RefercentType分配在托管椎上,受垃圾收集器的控制。
下面的代码和图演示了引用类型和值类型之间的一些差别:
注意:SomeVal v1=new SomeVal(); //分配在堆栈
这段代码不是在托管椎上分配的一个SomeVal实例,因为SomeVal是一个ValueType,编译器把v1初始化二进制意义上的0。也可以这样写:SomeVal
v1;
该行代码也会产生将实例分配在线程堆栈上,并将其所有字段置0 的IL 指令
两者惟一的差别是如果我们使用了new 操作符,那么C#将认为实例已经得到了初始化。
下面的代码会有助于我们的理解:
// 下面两行能够通过编译是因为C#认为
// v1 的所有字段首先被初始化成了0
SomeVal v1 = new SomeVal();
Int32 a = v1.x;
// 下面两行不能通过编译是因为C#认为
// v1 的字段没有得到初始化
SomeVal v1;
Int32 a = v1.x; // error CS0170: 使用了可能未赋值的字段“x”
(六)Box&Ubox
拆箱和装箱并不是严格意义上的互反操作。拆箱操作的代价要比装箱操作小许多。拆箱操作仅仅是获取指向对象中包含的值类型部分(数据字段)的指针而已,它不会像装箱操作那样涉及到任何内存字节的拷贝。然而,紧接着拆箱之后典型的操作往往就是字段拷贝,这两个操作合起来与装箱操作才成为真正的互反操作。
理解代码什么时候进行Box和UBox有助于我们提供程序的性能。
|