[你必須知道的.NET] 第十一回:參數之惑---傳遞的藝術(上)
[2] [你必須知道的.NET] 第十一回:參數之惑---傳遞的藝術(上)
系列文章導航:
[你必須知道的.NET] 第四回:后來居上:class和struct
[你必須知道的.NET] 第五回:深入淺出關鍵字---把new說透
[你必須知道的.NET] 第六回:深入淺出關鍵字---base和this
[你必須知道的.NET] 第七回:品味類型---從通用類型系統開始
[你必須知道的.NET] 第八回:品味類型---值類型與引用類型(上)-內存有理
[你必須知道的.NET] 第九回:品味類型---值類型與引用類型(中)-規則無邊
[你必須知道的.NET] 第十回:品味類型---值類型與引用類型(下)-應用征途
[你必須知道的.NET] 第十一回:參數之惑---傳遞的藝術(上)
[你必須知道的.NET] 第十二回:參數之惑---傳遞的藝術(下)
[你必須知道的.NET] 第十三回:從Hello, world開始認識IL
[你必須知道的.NET] 第十四回:認識IL代碼---從開始到現在
[你必須知道的.NET] 第十六回:深入淺出關鍵字---using全接觸
[你必須知道的.NET]第二十二回:字符串駐留(上)---帶著問題思考
[你必須知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二
本文將介紹以下內容:
• 按值傳遞與按引用傳遞深論
• ref和out比較
• 參數應用淺析
1. 引言
接上回《第九回:品味類型---值類型與引用類型(中)-規則無邊》中,對值類型和引用類型的討論,其中關于string類型的參數傳遞示例和解釋,引起園友的關注和討論,可謂一石激起千層浪。受教于裝配腦袋的深切指正,對這一概念有了相當進一步的了解,事實證明是我錯了,在此向朋友們致歉,同時非常感謝大家的參與,尤其是裝配腦袋的不倦相告。
因此,本文就以更為清晰的角度,把我理解有誤的雷區作做以深入的討論與分析,希望通過我的一點點努力和探討至少對如下幾個問題能有清晰的概念:
• 什么是按值傳遞?什么是按引用傳遞?
• 按引用傳遞和按引用類型參數傳遞的區別?
• ref與out在按引用傳遞中的比較與應用如何?
• param修飾符在參數傳遞中的作用是什么?
2. 參數基礎論
簡單的來說,參數實現了不同方法間的數據傳遞,也就是信息交換。Thinking in Java的作者有過一句名言:一切皆為對象。在.NET語言中也是如此,一切數據都最終抽象于類中封裝,因此參數一般用于方法間的數據傳遞。例如典型的Main入口函數就有一個string數組參數,args是函數命令行參數。通常參數按照調用方式可以分為:形參和實參。形參就是被調用方法的參數,而實參就是調用方法的參數。例如:
Code
由上例可以得出以下幾個關于參數的基本語法:
• 形參和實參必須類型、個數與順序對應匹配;
• 參數可以為空;
• 解析Main(string [] args),Main函數的參數可以為空,也可以為string數組類,其作用是接受命令行參數,例如在命令行下運行程序時,args提供了輸入命令行參數的入口。
• 另外,值得一提的是,雖然CLR支持參數默認值,但是C#中卻不能設置參數默認值,這一點讓我很郁悶,不知為何?不過可以通過重載來變相實現,具體如下:
Code
3. 傳遞的基礎
接下來,我們接上面的示例討論,重點將參數傳遞的基礎做以交代,以便對參數之惑有一個從簡入繁的演化過程。我們以基本概念的形式來一一列出這些基本概念,先混個臉兒熟,關于形參、實參、參數默認值的概念就不多做交代,參數傳遞是本文的核心內容,將在后文以大量的筆墨來闡述。所以接下來的概念,我們就做以簡單的引入不花大量的精力來討論,主要包括:
3.1 泛型類型參數
泛型類型參數,可以是靜態的,例如MyGeneric<int>;也可以是動態的,此時它其實就是一個占位符,例如MyGeneric<T>中的T可以是任何類型的變量,在運行期動態替換為相應的類型參數。泛型類型參數一般也以T開頭來命名。
3.2 可變數目參數
一般來說參數個數都是固定的,定義為集群類型的參數可以實現可變數目參數的目的,但是.NET提供了更靈活的機制來實現可變數目參數,這就是使用param修飾符。可變數目參數的好處就是在某些情況下可以方便的提供對于參數個數不確定情況的實現,例如計算任意數字的加權和,連接任意字符串為一個字符串等。我們以一個簡單的示例來展開對這個問題的論述,為: