|
1、 類型,對象,堆棧和托管堆 C#的類型和對象在應(yīng)用計算機(jī)內(nèi)存時,大體用到兩種內(nèi)存,一個叫堆棧,另一個叫托管堆,下面我們用直角長方形來代表堆棧,用圓角長方形來代表托管堆。
首先討論一下方法內(nèi)部變量的存放。 先舉個例子,有如下兩個方法,Method_1和Add,分別如下: public void Method_1() { int value1=10; //1 int value2=20; //2 int value3=Add(value,value); //3 } public int Add(int n1,int n2)//4 { rnt sum=n1+n2;//5 return sum;//6 } 這段代碼的執(zhí)行,用圖表示為:
上述的每個圖片,基本對應(yīng)程序中的每個步驟。在開始執(zhí)行Method_1的時候,先把value1壓入堆棧頂,然后是value2,接下來的是調(diào)用方法Add,因為方法有兩個參數(shù)是n1和n2,所以把n1和n2分別壓入堆棧,因為此處是調(diào)用了一個方法,并且方法有返回值,所以這里需要保存Add的返回地址,然后進(jìn)入Add方法內(nèi)部,在Add內(nèi)部,首先是給sum賦值,所以把sum壓入棧項,然后用return返回,此時,先前的返回地址就起到了作用,return會根據(jù)地址返回去的,在返回的過程中,把sum推出棧頂,找到了返回地址,但在Method_1方法中,我們希望把Add的返回值賦給value3,此時的返回地址也被推出堆棧,把value3壓入堆棧。雖這個例子的結(jié)果在這里沒有多大用途,但這個例子很好的說明了在方法被執(zhí)行時,變量與進(jìn)出堆棧的情況。這里也能看出為什么方法內(nèi)部的局變量用過后,不能在其他方法中訪問的原因。
其次來討論一下類和對象在托管堆和堆棧中的情況。 先看一下代碼: class Car { public void Run() { Console.WriteLine("一切正常"); } public virtual double GetPrice() { return 0; } public static void Purpose() { Console.WriteLine("載人"); } } class BMW : Car { public override double GetPrice() { return 800000; } } 上面是兩個類,一個Father一個Son,Son繼承了Father,因為你類中有一個virtual的BuyHouse方法,所以Son類可以重寫這個方法。 下面接著看調(diào)用代碼。 public void Method_A() { double CarPrice;//1 Car car = new BMW();//2 CarPrice = car.GetPrice();//調(diào)用虛方法(其實調(diào)用的是重寫后的方法) car.Run();//調(diào)用實例化方法 Car.Purpose();//調(diào)用靜態(tài)方法 } 這個方法也比較簡單,就是定義一個變量用來獲得價格,同時定義了一個父類的變量,用子類來實例化它。 接下來,我們分步來說明。 看一下運行時堆棧和托管堆的情部我:
這里需要說明的是,類是位于托管堆中的,每個類又分為四個類部,類指針,用來關(guān)聯(lián)對象;同步索引,用來完成同步(比如線程的同步)需建立的;靜態(tài)成員是屬于類的,所以在類中出現(xiàn),還有一個方法列表(這里的方法列表項與具體的方法對應(yīng))。 當(dāng)Method_A方法的第一步執(zhí)行時: 當(dāng)Method_A方法執(zhí)行到第二步,其實第二步又可以分成 Car car; car = new BMW(); 先看Car car;
car在這里是一個方法內(nèi)部的變量,所以被壓到堆棧中。 再看 car = new BMW(); 這是一個實例化過程,car變成了一個對象
這里是用子類來實例化父類型。對象其實是子類的類型的,但變量的類型是父類的。 接下來,在Method_A中的調(diào)用的中調(diào)用car.GetPrice(),對于Car來說,這個方法是虛方法(并且子類重寫了它),虛方法在調(diào)用是不會執(zhí)行類型上的方法,即不會執(zhí)行Car類中的虛方法,而是執(zhí)行對象對應(yīng)類上的方法,即 BMW中的GtPrice。 如果Method_A中執(zhí)行方法Run(),因為Run是普通實例方法,所以會執(zhí)行Car類中的Run方法。 如果調(diào)用了Method_A的Purpose方法,即不用變量car調(diào)用,也不用對象調(diào)用,而是用類名Car調(diào)用,因為靜態(tài)方法會在類中分配內(nèi)存的。如果用Car生成多個實例,靜態(tài)成員只有一份,就是在類中,而不是在對象中 |
|
|