Refactoring重構函數
在C#裡,VS提供一個很簡報的方式,可以幫助我們把現有的程式碼片段,輕易地轉換成一個區域函數(Method),讓Programmer可以很輕鬆的管理開發的程式碼。
使用方式:
- 將欲轉換的程式碼圈選。
- 按下Ctrl + . (period)。
- 選擇Extract Method。
- 命名新的函數與呼叫函數名稱。
用refactoring方式產生的區域函數,在使用上是不使用「this」來呼叫函數的,且產生的函數識別字中也多了「static」的字樣,與一般自行新增的不同(日後詳細補充static的細節)。
用「值」或「參考」來傳遞參引數
平常呼叫函數時,我們通常都是值的方式傳遞給函數去運算,這樣可以有效確保原本變數的值不被改變、維持獨立性,但有時候我們可能也需要讓函數去處理同一個值、而不是複製的分身,此時我們便需要利用「Reference」的方式,讓函數可以處理同一個變數的值,例如:
Private vodi CalculateFutureValue ( decimal monthlyinvestment, decimal monlyInterestRate, int months, ref decimal futureValue)
{
for (int i = 0; i < months; i++)
[
futureValue = (futureValue + monthlyInestment) * (1 + monthlyInterestRate);
}
}
上述例子因為第四個參數是用「ref」的方式,因此該函數處理的是與主程式同一個函數的值,因此這個函數就不需要有回傳,futureValue已經擁有算數處理過的結果了。
參考的參數傳遞方式有兩種,分別是「ref」跟「out」的方式,格式如下:
[ { ref | out } ] type variableName
「ref」跟「out」主要的差別是使用「out」時,該變數可以不事先初始化,但在呼叫的函數程式執行結束前,必須要將值賦予給這個變數。
關於參數傳遞使用值或參考方式,有幾點注意事項:
- 通常使用「值」來進行傳遞是比較好的寫程式習慣,這樣變數不會被函數干擾或更改。
- 使用「ref」會比「out」的習慣來得好,因為總是先初始化一個變數的數值是比較良好的習慣。
- 使用「out」的例外時機是,當我們想使用「TryParse」這類的函數時,因為它的函數在定義第二個參數時,便已指名需要用「out」的模式來傳遞參數了。
- 用「ref」跟「out」的方式回傳參數時,通常用一個「Object」會比單獨回傳個別的值來得好。
- 當我們回傳參考時,被呼叫的函數就不用再寫return了。
「實值 Value Type」與「參考 Reference Type」型別
根據MSDN文件說明:「C#有兩種資料型別:實值與參考,通常是須考量應用程式的效能時,或是管理資料與記憶體時,這部分的差異便顯得格外重要。」當變數是以基本內建資料型別的其中一種方式,或是使用者定義的結構進行宣告時,這類的變數便是實值型別 (Value Type),而其中有一個例外是「string」資料型別,它是屬於參考型別。
實值型別會將內容儲存在配置於堆疊的記憶體中,例如 int x = 42; 其中的42會存在堆疊的記憶體區域中,當變數X因為定義的方法完成執行而超出範圍時,堆疊就會捨棄此值。使用堆疊很有效率,但是實值型別有限的存留期,讓它並不適合在不同類別之間共用資料。
相反地,參考性別(例如類別或陣列)會將內容配置在堆積(Heap)的不同記憶體區域,當方法完成時,這段記憶體並不會歸還給堆積,只有當C#的記憶體回收系統判定不需要它時才會回收,雖然在宣告參考型別時會需要較大的額外負荷,但是它們具有可以從其他類別存取的優點。
這部分日後有機會會再撰文補充。
呼叫函數 (Calling Method) 與被呼叫的函數 (Called Method)
註:原文書討論這類呼叫函數 (Calling Method) 與被呼叫的函數 (Called Method) 時會讓人有點混淆,這邊舉個簡單例子來說明:
// f () 此函數含有呼叫g()的函數,因此是「呼叫函數 Calling Method」void f()
{
g();
}
// g() 為實際被呼叫函數,因此是「被呼叫函數 Called Method」void g()
{
}