方法的參數有六種,分別是值參數、引用參數、輸出參數、參數數組、命名參數、可選參數。
值參數
值參數是方法的默認類型,通過復制實參的值到形參的方式把數據傳遞到方法,方法被調用時,系統作兩步操作;
- 在棧中為形參分配空間。
- 復制實參到形參。
1)在方法被調用前,用作實參的變量a1的引用已經在棧里了。
2)隨着方法的開始,系統在棧中為形參分配空間,並從實參復制值。
3)因為a1是引用類型,所以引用被復制,結果實參和形參都引用堆中的同一個對象。
4)因為a2是值類型,所以值被復制,產生了一個獨立的數據。
5)在方法執行后,形參被從棧中彈出。
6)a2、值類型,它的值不受方法行為的影響。
7)a1、引用類型,它的值被方法的行為改變了。
引用參數
- 使用引用參數時,必須在方法的聲明與調用中使用ref修飾符。
- 實參必須是變量,在用作實參前必須賦值。
對於值參數,系統在棧上為形參分配內存;相反,對於引用參數,形參的參數名看起來就好像是實參變量的別名,也就是說,它們指向的是相同的內存位置。所以在方法的執行過程中對形參作的任何改變,在方法執行完成后依然有效(表現在實參變量上)。
引用參數的傳遞,對值類型與引用類型都是完全傳遞,不存在復制值與復制引用,即引用相同的內存位置。
輸出參數
輸出參數用於從方法體內把數據傳遞到調用代碼,它非常類似引用參數。
1,必須在方法的聲明與調用中使用out修飾符。
2,和引用參數相似,實參必須是變量。
就像引用參數,輸出參數的形參擔當實參的別名,方法內對形參的任何改變在方法執行完成后,通過實參變量都可見。
與引用參數的不同,輸出參數有以下2個要求。
- 在方法內部,輸出參數在被讀取之前必須被賦值,這意味着參數的初始值是無關的,因此沒有必要在方法調用之前為實參賦值。
- 在方法返回前,方法內部的任何貫穿的可能路徑都必須為所有輸出參數進行一次賦值。
參數數組
上面3中參數方式,必須嚴格的一個實參對應一個形參,參數數組不一樣,它允許零個或多個實參對應一個特殊的形參。
參數數組的要求如下:
- 在一個參數列表中只能有一個參數數組。
- 如果有,它必須是列表中的最后一個。
聲明參數數組,必須要有params修飾符(調用不需要修飾符),必須是一種類型的數組。
使用分散式傳參時,編譯器做如下事:
1)接受實參列表,用它們在堆中創建並初始化一個數組。
2)把數組的引用保存到棧中的形參里。
3)如果在對應的形參數組的位置沒有實參,編譯器會創建一個有零個元素的數組來使用。
4)如果數組參數是值類型,那么值被復制,實參不受方法內部的影響。
5)如果數組參數是引用類型,那么引用被復制,實參引用的對象可以受到方法內部的影響。
在使用數組式傳參時,編譯器使用你的數據而不是重新創建一個。即相當引用參數。
命名參數
上面用到的四種參數,都是位置參數,也就是說每個實參的位置必須一一對應相應的形參位置。
從.Net4.0開始,只要顯示指定參數的名字,就可以以任意順序在方法調用中列出實參,細節如下。
1.方法的聲明沒有什么不一樣。形參已經有名字了。
2.不過在調用方法的時候,形參的名字后面跟着冒號和實際的參數值或表達式。
在調用的時候,也可以位置參數和命名參數混合使用,但是所有的位置參數必須先列出,
可選參數
可選參數是.Net4.0才加入的,在調用方法的時候可以包含這個參數,也可以省略它。
為了表明某個參數是可選的,你需要在方法聲明的時候為參數提供默認值。制定默認值的語法和初始化本地變量的語法一樣。
如下圖
1)形參b設置成了默認值。
2)因此,在調用方法的時候只有一個參數,方法會使用3作為第二個參數的初始化。
對於可選參數的聲明,有幾個重要事項:
1.不是所有的參數類型都可以作為可選參數。
1)只要值類型的默認值在編譯的時候可以確定,就可以使用值類型作為可選參數。
2)只有在默認值是null的時候,引用類型才可以作為可選參數來使用。
3)可選參數只能是值參數。
2.所有必填參數必須在可選參數聲明之前聲明,如果有params參數,必須在所有可選參數之后聲明。
3.必須從可選參數列表的最后開始省略,一直到開頭,否則會造成參數歧義。
4.若想消除參數歧義,可以結合命名參數和可選參數的特性。
如下圖