CodeGym /課程 /C# SELF /區域函式

區域函式

C# SELF
等級 11, 課堂 4
開放

1. 前言

每個寫 code 的人都知道:函式(或叫方法)基本上就是任何應用程式的「工作馬」。它們幫我們把程式碼結構化、重複利用邏輯,還能避免一直 copy paste 到天荒地老。到目前為止,你遇到的所有函式,都是 class 或 struct 裡的「鄰居」。

但想像一下,如果你有一個很大的函式,裡面有一小段邏輯你想抽出來,但又不想讓整個專案都看到它。比如說,一個只在這個方法裡才需要的小計算。

這時候,區域函式 就派上用場啦。

區域函式 就是宣告在另一個函式(方法、建構子、屬性,甚至另一個區域函式)裡的函式。這種區域函式只會被「老爸」看到,其他地方都看不到。

區域函式語法


void MainMethod()
{
    Console.WriteLine("開始執行主方法。");            // 開始執行主方法。
    int result = InnerSum(5, 7);                              // 呼叫區域函式 InnerSum(內部加總)
    Console.WriteLine($"區域函式結果: {result}");    // 區域函式結果: {result}

    // 區域函式直接在 MainMethod 裡宣告
    
  
int InnerSum(int a, int b) // 區域函式:兩個數字相加 { return a + b; // 回傳 a 跟 b 的加總 }
}

在這個例子裡,InnerSum 這個函式是直接寫在 MainMethod 裡的。它在主方法外面完全看不到——就像一個只有你自己知道的小祕密指令。

2. 怎麼宣告、什麼時候用區域函式

基本規則

  • 區域函式可以宣告在:方法、建構子、屬性、運算子,甚至另一個區域函式裡!
  • 區域函式只在自己的作用域(scope)裡看得到。
  • 你可以在父函式裡,宣告前或宣告後呼叫區域函式(C# 會自動幫你分析)。

範例:計算平均分數


// 主要函式:印出平均分數
void PrintAverageScore(int[] scores)
{
    if (scores.Length == 0)
    {
        Console.WriteLine("沒有分數可以計算。"); // 沒有分數可以計算。
        return;
    }

    double average = CalculateAverage(scores);
    Console.WriteLine($"平均分數: {average:0.00}"); // 平均分數

    // 區域函式:計算平均值
    
  
double CalculateAverage(int[] arr) { int sum = 0; foreach (var score in arr) sum += score; return (double)sum / arr.Length; // 回傳平均值 }
} // 呼叫函式: int[] myScores = { 5, 4, 3, 4, 5 }; PrintAverageScore(myScores); // 會印出:平均分數: 4.20

有沒有很方便?PrintAverageScore 外面的人完全不能用它裡面的區域函式 CalculateAverage。這種寫法可以讓你的 code 很整齊,也不會把一堆輔助方法塞到全域命名空間裡。

3. 區域函式跟作用域(scope)

區域函式最大的特色就是——它的作用域只在「老爸」方法裡。這樣可以避免 class 裡一堆只用一次的小方法亂飛。


+-----------------+
|   類別方法      |
|    void Foo()   |
|                 |
|   +-----------+ |
|   |  區域函式 | |
|   +-----------+ |
+-----------------+
區域函式只存在於宣告它的方法裡

區域函式只會存在於宣告它的方法裡。你如果想在外面呼叫它,就像打電話給一條不存在的祕密專線一樣,完全沒門。

如果你不小心在父方法外面呼叫區域函式,會直接編譯錯誤:名稱 '...' 在目前的內容不存在。

區域函式可以看到父方法的變數

區域函式可以存取父方法裡的所有變數——這就是它超強的地方!


void ShowStudent(string name, int age)
{
    string message = BuildMessage();
    Console.WriteLine(message);

    // 區域函式用到 "name" 跟 "age" 變數
    
  
string BuildMessage() { return $"名字: { name}, 年齡: { age}"; }
}

這樣寫不只更短,也不會讓 code 很吵。你不用每次都傳一堆參數進去——區域函式直接「看」到父方法的所有東西。

4. 區域函式可以寫在迴圈或條件裡

區域函式可以寫在任何巢狀層級——甚至在迴圈或 if 裡面:


void ProcessNumbers(int[] numbers)
{
    foreach (int number in numbers)
    {
        if (number % 2 == 0)
        {
            Console.WriteLine($"{number} — 偶數");
            PrintEvenMessage();
        }
        else
        {
            Console.WriteLine($"{number} — 奇數");
        }

        
  
void PrintEvenMessage() { Console.WriteLine("這是偶數,恭喜!"); }
} }

不過這種寫法如果區域函式太多或太長,code 會很難讀。不要亂用,但知道可以這樣做還是很有幫助。

區域函式 vs 一般 private 方法

比較項目 區域函式 類別 private 方法
作用域 只有父函式 整個類別
能不能存取父變數 可以 不行(只能靠參數)
易讀性 很高 普通
重複利用潛力 低 高
好不好測試 不好測 很好測

5. 常見錯誤跟實作細節

錯誤一:拼錯或忘記宣告區域函式。
如果你呼叫區域函式時名字打錯或根本沒宣告,編譯器會報 CS0103 或 CS0128,然後 code 直接不能跑。

錯誤二:改到被捕捉的變數(closure)。
如果區域函式去改父方法的變數,結果可能跟你想的不一樣——被捕捉的變數有時像複製,有時像參考,改了會影響邏輯。

錯誤三:忽略 IDE 建議把 private 方法變成區域函式。
如果你在 class 裡留一堆沒必要的 private 方法,IDE(像 Rider)建議你改成區域函式卻不理它,code 很快就會變亂,越來越難讀。

錯誤四:區域函式巢狀太深。
巢狀太多層的函式會讓人看不懂、debug 也很痛苦。簡潔才是王道。

2
任務
C# SELF, 等級 11, 課堂 4
上鎖
使用區域函式計算兩個數字的總和
使用區域函式計算兩個數字的總和
2
任務
C# SELF, 等級 11, 課堂 4
上鎖
用來檢查數字奇偶性的本地函式
用來檢查數字奇偶性的本地函式
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION