Posted on 2008-04-02 23:33
ZelluX 閱讀(1548)
評論(14) 編輯 收藏 所屬分類:
OOP
這語言真不錯,不像Java那么呆,可惜不開源。
入門看的書是CLR via C#中文版,翻譯質量不錯,起碼到現在還沒覺得有必要翻一翻原版(不過為什么中文書都喜歡把“棧”叫成“堆棧”呢)。
前面幾章粗略看了下,從第四章類型基礎開始重點閱讀。
繼續漫無目的的學習感興趣的東西,學習之中經常會驚喜的發現,自己看問題的角度已經不同于之前了。
1. 類的new操作會遞歸調用該類的所有父類構造器,直到System.Object,后者的構造器只是簡單返回,用ILDasm查看MSCorLib.dll可以證實這一點。


.method?public?hidebysig?specialname?rtspecialname?
????????instance?void??.ctor()?cil?managed


{
??.custom?instance?void?System.Runtime.ConstrainedExecution.ReliabilityContractAttribute::.ctor(valuetype?System.Runtime.ConstrainedExecution.Consistency,
????????????????????????????????????????????????????????????????????????????????????????????????valuetype?System.Runtime.ConstrainedExecution.Cer)?=?(?01?00?03?00?00?00?01?00?00?00?00?00?)?
??//?Code?size???????1?(0x1)
??.maxstack??8
??IL_0000:??ret
}?//?end?of?method?Object::.ctor


2. is和as操作符,is類似于Java中的instanceof,as會先檢查類型,如果兼容返回該對象的引用,反之返回null。
Emplooee?e?=?o?as?Employee;

if?(e?!=?null)?
{
????//?blah
}利用as可以做到只檢驗一次對象類型,提高程序性能。這本書的很多地方都提到了性能因素。
3. 方法調用和x86上匯編語言調用機制很類似。先是參數入棧,接著返回地址入棧,返回的時候也差不多。
不知道x64等寄存器較多的架構上會不會使用寄存器傳參呢,呵呵。
4. 作為方法的prologue的一部分,CLR會自動將所有局部變量初始化為null或0。
感覺這個自動初始化沒什么必要,在第五章可以看到。
SomeVal?v1;
SomeVal?v1?=?new?SomeVal();這里的SomeVal都是值類型,CLR都會將它們初始化為0。區別在于C#認為前者沒有初始化,直接使用這個值會報錯;而后者在不賦值的情況下使用這個值。
可能這是CLR和C#之間不統一導致的冗余步驟吧。
5. CLR開始在一個進程中運行時,會給System.Type類型創建一個實例,每個類都會包含指向System.Type類型的指針。
6. CLR提供了執行溢出檢查的計算指令,例如add.ovf對應add,mul.ovf對應mul。C#中默認關閉溢出檢查。
可以使用checked關鍵字使用溢出檢查。一般情況下,對預計可能發生溢出的代碼放到checked塊中,對允許溢出的代碼(比如計算hash值)放到一個unchecked塊中,其他情況,Debug時打開編譯器的/checked+開關,Release版本關閉。
7. 所有的值類型都是從System.ValueType繼承的。后者重寫了Equals方法,比較兩個值對象是否完全相等。
8. boxing和unboxing。
boxing:托管堆中分配內存,復制值類型,然后返回對象地址。
unboxing:相當于一個通過指針取值的過程,不過這個指針是已裝箱部分中的實際值部分。
9. FCL(Framework Class Library)中包含了支持值類型的泛型容器類,不需要對容器中的元素進行boxing/unboxing處理。
不過這里就有個問題了,值類型的話是放在棧上的,生命周期小于容器的,這個怎么處理呢?第16章才詳細解釋泛型,先把這個問題留著吧 =,=
10. 依然是性能問題。有時候編譯器會反復對一個值類型boxing,此時手動boxing會提高一些性能。
Int32?v?=?5;
//?需三次boxing
Console.WriteLine("{0},?{1},?{2}",?v,?v,?v);

//?只需一次boxing
Object?o?=?v;
Console.WriteLine("{0},?{1},?{2}",?o,?o,?o);

接下來書上舉了個很搞的例子說明boxing和unboxing的各種情況,其實也很容易理解。