昨晚,無事,隨手翻了翻《
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。
有寫得不正確的地方,請指教。
-------------------------------------------------------------------------------------------------------------------------------------------------------
2007y11m9d補充
六
基元與基元之間的轉換
第五節的強制類型轉換,只是針對引用類型,沒有講到值類型。
基元是值類型的一部分,即數字類型(
Int32,byte,char,float等)。
基元在
CLR中都有一個對應的別名,比如
int等價
System.Int32,
string等價
System.String,
object等價
System.Object。
String和
Object不是值類型,(內置的引用類型)
基元與基元之間的轉換在
CLR中有一套比較負責的機制,但總的來說,不同類型之間的基元轉換時,小的數據類型可以向大的數據類型轉化,但是大的數據類型向小的數據類型轉換時,要小心數據溢出,
C#編譯器在默認情況下是不檢查基元類型操作時發生的數據溢出,也就是說在發生溢出時,不拋出異常,想想多麼可怕。所以應該盡量避免使用不同類型的基元操作,或者在編譯時檢查數據溢出,使用
checked 關鍵字,讓程序拋出異常,記住
checked耗費性能。
還有,並不是所有類型的基元都可以相互轉換的,
CLR有自己的一套規則,我也不想記,太多了,以後再研究,哈哈!