參考型別與實值型別

來源:互聯網
上載者:User

摘錄:

線程堆棧和線程堆:都是記憶體地區,實值型別分配在堆棧上【後進先出】;參考型別變數分配在堆棧上,內容分配在堆上;

1.實值型別

a.實值型別包括結構和枚舉,參考型別包括類、介面、委託等。還有一種特殊的實值型別,稱為簡單類型(Simple Type),比如 byte,int等

b.所有的實值型別都隱式地繼承自 System.ValueType類型(注意System.ValueType本身是一個抽象類別),所以不能顯示讓一個實值型別(結構)再繼承另外一個類,因為c#不支援多重繼承,而System.ValueType和所有的參考型別都繼承自 System.Object基類,

c.當聲明一個實值型別的變數(Variable)的時候,變數本身包含了實值型別的全部欄位,該變數會被分配線上程堆棧(Thread Stack)上。

d.編譯器隱式地會為結構類型建立了無參數建構函式。在這個建構函式中會對結構成員進行初始化,所有的實值型別成員被賦予0或相當於0的值(針對Char類型),所有的參考型別被賦予null值。(因此,Struct類型不可以自行聲明無參數的建構函式)。所以,我們可以通過隱式聲明的建構函式去建立一個ValPoint類型變數:

    public struct ValPoint
    {
        public int x;
        public ValPoint(int x)
        {
            this.x = x;
        }
    }

ValPoint vPoint1 = new ValPoint(); Console.WriteLine(vPoint.x); // 輸出為0   我們將上面代碼第一句的運算式由“=”分隔拆成兩部分來看:   

•左邊 ValPoint vPoint1,在堆棧上建立一個ValPoint類型的變數vPoint,結構的所有成員均未賦值。在進行new ValPoint()之前,將vPoint壓到棧上。   

•右邊new ValPoint(),new 操作符不會分配記憶體,它僅僅調用ValPoint結構的預設建構函式,根據建構函式去初始化vPoint結構的所有欄位。

注意上面這句,new 操作符不會分配記憶體,僅僅調用ValPoint結構的預設建構函式去初始化vPoint的所有欄位。那如果我這樣做,又如何解釋呢?  

Console.WriteLine((new ValPoint()).x);     // 正常,輸出為0  

//在這種情況下,會建立一個臨時變數,然後使用結構的預設建構函式對此臨時變數進行初始化。

 

2.引用類型   

public class RefPoint
    {
        public int x;
        public RefPoint(int x)
        {
            this.x = x;
        }
        public RefPoint() { }
    }

當我們僅僅寫下一條聲明語句:  

RefPoint rPoint1;   //它的效果是僅僅在堆棧上建立一個不包含任何資料,也不指向任何對象(不包含建立在堆上的對象的地址)的變數。

而當我們使用new操作符時:  

rPoint1= new RefPoint(1);

會發生這樣的事:

1.在應用程式堆(Heap)上建立一個參考型別(Type)的執行個體(Instance)或者叫對象(Object),並為它分配記憶體位址。

2.自動傳遞該執行個體的引用給建構函式。(正因為如此,你才可以在建構函式中使用this來訪問這個執行個體。)

3.調用該類型的建構函式。

4.返回該執行個體的引用(記憶體位址),賦值給rPoint變數。

 

/////////////小結值參數、參考型別參數、輸出參數///////////////////////////

1.值參數

資料通過複製實參的值傳給形參,方法被調用時,系統做如下操作:

A.在棧中為形參分配空間

B.複製實參的值到形參,這樣形參中的值的改變不會影響原來實參中的值,只是原來實參值的一份拷貝。

------------實參不一定是變數,它可以是任何能計算成相應資料類型的運算式。

2.引用參數

必須在方法地聲明和調用中都使用ref修飾符,實參必須是變數,在用作實參前必須被賦值,如果是參考型別變數,可以賦值為一個引用或null值

A.不在棧中為形參分配新的記憶體

B.形參的名稱相當於實參變數的別名,跟實參一樣引用相同的記憶體位置。

3.輸出參數

用於從方法體內把資料傳出到調用代碼,它們非常類似於引用參數。

A.必須在聲明的調用中都使用out修飾符

B.實參必須是變數,不能是其他運算式類型

C.不在棧中為形參分配新的記憶體

D.形參的名稱相當於實參變數的別名,跟實參一樣引用相同的記憶體位置。

E.在方法內部,輸出參數在被讀取之前必須被賦值。

F.每個輸出參數在方法返回之前必須被賦值。

4.參數數組

它允許零個或多個實參對應一個特殊的形參。

A.在一個參數列表中只能有一個參數數組

B.如果有,它必須是列表中的最後一個

eg: void ListInts(params int[] inVals)     {     }

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.