.NET框架程序设计--类型基础
 

2009-12-31 作者:杨宝明 来源:网络

 

值得注意的几个地方

(一)类型转换的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分配在托管椎上,受垃圾收集器的控制。

下面的代码和图演示了引用类型和值类型之间的一些差别:

// 引用类型(因为 ’class’的缘故)
class SomeRef public Int32 x; }
// 值类型(因为 ’struct’的缘故)
struct SomeVal public Int32 x; }
static void ValueTypeDemo() {
SomeRef r1 = 
new SomeRef(); // 分配在托管堆上
SomeVal v1 = new SomeVal(); // 分配在堆栈上
r1.x = 5; // 解析指针
v1.x = 5; // 在堆栈上修改
Console.WriteLine(r1.x); // 显示为 “5”
Console.WriteLine(v1.x); // 也显示为 “5”
// 图5.1 左边的一幅展示了上面的代码执行后的情形
SomeRef r2 = r1; // 仅拷贝引用(指针)
SomeVal v2 = v1; // 先在堆栈上分配,然后拷贝成员
r1.x = 8; // 改变了r1.x 和 r2.x
v1.x = 9; // 改变了v1.x,没有改变v2.x
Console.WriteLine(r1.x); // 显示为 “8”
Console.WriteLine(r2.x); // 显示为 “8”
Console.WriteLine(v1.x); // 显示为 “9”
Console.WriteLine(v2.x); // 显示为 “5”
// 图5.1 右边的一幅展示了上面所有的代码执行后的情形
}

注意: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有助于我们提供程序的性能。

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。

资源网站: UML软件工程组织