這章不好理解,我是連抄帶找的。。。。。。。。。。。
一、system.object
所有型別的基類,也就是所有型別從它派生。
公開了幾個方法:
equals : 判定兩個物件是否具有相同的值(相等性和同一性後續討論 )
gethashcode
tostring() 預設返回型別的完整名稱,但是經常會重寫返回表示物件狀態的
string
。例如:
int32
的tostring()
顯示欄位的值
gettype:返回從
type
派生的乙個型別的例項,呼叫的物件是什麼型別。
memberwsiseclone: 深度拷貝
finalize : 在垃圾**器判定物件是垃圾後,在物件的記憶體被實際**之前,呼叫這個虛方法。需要在**記憶體之氣那執行新區管理工作的型別應該重寫該方法。順便說下:
finalize
是會先執行父類
finalize
如果父類
finalize
執行後,子類再執行
finalize
時候會引發異常。具體後面介紹。
二、new 關鍵字
dog dog= new dog(「旺財」);
作用1、計算型別及其所有基型別(一直到 system.object )中定義的所有例項欄位所需要的位元組數。物件含有額外位元組開銷,(
1.型別物件指標
2.同步索引快 )
clr利用這些成員管理物件。額外成員的位元組數要計入物件的大小
2、從託管堆中分配型別要求的位元組數,從而分配物件的記憶體,分配的所有位元組都設為零(0)
3、初始化物件的型別指標和同步索引成員
4、呼叫型別的例項構造器,傳遞在new呼叫中指定的實參(
eg:旺財)編譯器都在構造器中自動生成**來呼叫基類構造器 ,每個型別的構造器否負責初始化該型別定義的例項字段,最終呼叫
system.object
的構造器。因為沒有定義任何例項字段所以該構造器什麼都不做,直接返回。
三、型別轉換 is 和
as1、型別轉化規則: 子類可以直轉為基類
public class dog:anmial{}
狗是動物, anmial animal=new dog();
基類不能直接轉化為子類
dog dog=new animal(); (x) 可以這麼理解編譯器要做型別推斷,但是呢動物不一定是狗還可能是人或者別的動物貓。另外,語法安全上也是要求不能直接從基類轉為子類。
2、is 和
as 型別需要轉化通常我們會這樣: 因此各自利弊自己選擇
void getname(anmial animal)
if(animal is dog) //此處會做兩次的型別檢查
,失敗返回
false
void getname(anmial animal)
dog dog=animal as dog; //此處會做一次次的型別檢查 ,失敗返回
null
if(dog !=nul)
四、執行時的相互關係
簡單方法的呼叫需要預先知道的術語:
a:程序、執行緒(後面章節詳細介紹)
b:執行緒棧:
clr建立執行緒時候會分配
1m序幕**(開場
):我也很無奈為啥翻譯成這個名字,
prologue
開始執行方法前初始化變數,在棧上分配記憶體
尾聲**(後記
):我也很無奈為啥翻譯成這個名字,
epilogue
執行完後清理記憶體並且返回到呼叫者。
程式執行開始後,載入乙個clr的乙個
windows
程序,程序有多個執行緒。執行緒建立時候會分配到
1m的棧,棧空間用於向方法傳遞實參,實參,實參,方法內部定義的區域性變數也在棧上,棧上已經有了一些資料了(頂部陰影)。現在執行到了
m3的方法。
執行m3時候,
clr會初始化
m3的方法,包括開場**和結束**,開場**用來初始化區域性變數並且分配記憶體,引用型別指向
null,
值型別設定為
1.執行時
-值型別的分配和方法呼叫
圖中3的返回位址是在
m3中呼叫執行
m2的時候,壓棧進去的,目的是告訴排程指標執行完
m2的時候記得返回這裡,執行
m2的時候類似的分配空間,執行完
m2之後 4,
5將會被結束**(
clr叫做尾聲**,這什麼鬼翻譯!)清除掉,專業術語叫做 棧針
unwind
行為,同時棧針指向
3繼續執行,當執行完
m3時候同樣重複清除,棧針指向呼叫
m3的返回位址,(該位址在 執行緒棧
0位置下方,
1位置上方一點)這樣就結束了方法呼叫。
同理要分配乙個執行緒棧,呼叫方法前,有個序幕**、和尾聲**。行為和上面講到的一致。
執行時-引用型別和方法的呼叫
此處我們更關注堆上的變化
當執行到 new的關鍵字作用:結算物件占用記憶體大小(物件的型別指標大小,同步索引快、區域性變數、基類型別消耗的字段等一直計算到
object
)之後上形成如圖:
17行**執行完畢後形成如下圖示:結合**部分注釋和下圖理解執行時和方法的呼叫。
type型別物件:所有型別物件的基類,它的型別物件指標指向自己。
現在解釋下
你方法中的的gettype() 時候自己沒有定義為什麼能呼叫到,開始我們講了這個呢是基類的
object
的非虛方法
gettype()
,而且圖中的
dog型別物件
animal
型別物件,都是
type
的乙個例項,因此就知道了你呼叫的物件的實際型別。(具體怎麼知道?看下面解釋)
型別本質上也是物件,clr建立型別物件時,必須初始化以上型別在分配時包含的成員,初始化成什麼呢?clr開始在乙個程序中執行時,會立即為強命名程式集
mscorlib.dll
中定義的
system.type
型別建立乙個特殊的型別物件。
而我們自定義的使用者型別都是該型別的「例項
」。也就是物件指標指向 type型別物件。
當我們呼叫gettype()是時候返回的是:存貯在特定型別物件上的成員的位址指標。
這個怎麼理解呢就是你呼叫dog.gettype()返回的是存貯在
type
型別上的物件型別指標位址,
即dog
型別物件指標,返回了
dog型別物件指標自然就知道了
dog是什麼型別了。
物件型別指標和同步索引快、字段空間、方法位址空間=**。以後以**相稱
第四章 型別基礎
4.1 所有型別都從system.object派生 執行時 要求每個型別最終都從system.object型別派生。system.object 公共例項方法 equals 如果兩個物件具有相同的值,就返回true。gethashcode 返回物件的值得雜湊碼。如果某個型別的物件要在雜湊表集合中作為建...
《CLR via C 》第四章《型別基礎》
在coding中,任何型別都是繼承於system.object的,形如public class physicalgc basecommand其實完整的寫法應該是public class physicalgc basecommand system.object既然繼承了system.object,那就...
第四章 復合型別
第一題 按示例請求顯示資訊。第二題 修改程式4.4,使用c string類 include include using namespace std int main 第三題 使用char陣列,和cstring中的函式,按示例格式顯示輸出 include include using namespace...