昨晚,无事,随手翻了翻《CLR 架构设计》,看到“类型”一章,感触颇多,心中窃喜。大清早来公司,写下这点心得,一是怕久后忘记,也可以相互学习。
一 .NET所有类型都(隐示)继承System.Objet,地球人都知道。
二 .NET类型分两类,一类是值类型(valueType),一类是引用类型(referenceType)
值类型包括两类;枚举,结构。
结构又细分为; 数字类型(比如Int32,float等),bool类型 ,用户结构(比如struct)。
值类型之外的类型都是引用类型,String和Object为内置的引用类型。
三 值类型和引用类型在内存中分配的空间不同
值类型一般分配在栈中(stack),优点是访问速度快,事后不需要GC执行垃圾回收。
比如在函数中定义一个局部变量i(Int32 i=0),在i没都被函数使用之前,i一直呆在栈中。
引用类型的对象一般分配在堆中(heap),缺点是访问速度慢,事后需要GC执行垃圾回收(因为分配在堆中的对象需要事先到栈中,找到自己的指针,才能被引用)。
四 装箱子与拆箱子
其实,我们每敲一行DEMO,都有 装箱子与拆箱子 在发生。
先解释,什么是装箱子,装箱子就是把前面提到的值类型对象转化成引用类型(value to reference)。
拆箱子,就是把引用类型对象转化成值类型(reference to value)。
举例,很多人都喜欢用这样使用,定义int i=0,i.toString();其实i.toString()这个操作就是装箱子。
Public class TestOne
{
Methed1(Object obj)
{
doanythings;
}
Public void main()
{
int i=1;
Methed1(i);
}
}
代码不多,就一个Methed1(Object obj)方法,在main方法中调用Methed1(i);实质也是一个装箱子的过程,
把int类型转化成System.Object类型。
Public class TestTwo
{
Public void main()
{
String str=“12345“;
Convert.ToInt32(str);
}
}
Convert.ToInt32(str)就是一个拆箱子,把引用类型转化成值类型。
五 强制类型转换(注意只对引用类型而言)
类型可以继承,假设有 类型A,类型B实际存在;B继承A,那么可以说A是父类,B是子类,地球人都知道。
A a=new A();
B b=new B();
a=b;OK
b=a; NO
b=(B)a;OK(强制类型)
子类可以(隐示)转换成父类,比如a=b。
父类可以(强制类型)换换成子类,比如b=(B)a。
IS和AS 都可以进行强制类型转化,但AS性能更好,AS如果转化失败,返回NULL。
IS返回true or false。
有写得不正确的地方,请指教。
-------------------------------------------------------------------------------------------------------------------------------------------------------
2007y
11m
9d补充
六 基元与基元之间的转换
第五节的强制类型转换,只是针对引用类型,没有讲到值类型。
基元是值类型的一部分,即数字类型(Int32,byte,char,float等)。
基元在CLR中都有一个对应的别名,比如int等价System.Int32,string等价System.String,object等价System.Object。
String和Object不是值类型,(内置的引用类型)
基元与基元之间的转换在CLR中有一套比较负责的机制,但总的来说,不同类型之间的基元转换时,小的数据类型可以向大的数据类型转化,但是大的数据类型向小的数据类型转换时,要小心数据溢出,C#编译器在默认情况下是不检查基元类型操作时发生的数据溢出,也就是说在发生溢出时,不抛出异常,想想多么可怕。所以应该尽量避免使用不同类型的基元操作,或者在编译时检查数据溢出,使用checked 关键字,让程序抛出异常,记住checked耗费性能。
还有,并不是所有类型的基元都可以相互转换的,CLR有自己的一套规则,我也不想记,太多了,以后再研究,哈哈!