☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
C# 基礎 初學

🔧 方法與函式

📌 什麼是方法?

方法(Method)就像一台自動販賣機

  • 你投入硬幣(參數
  • 機器處理(方法本體
  • 吐出飲料(回傳值

📌 方法宣告

// 方法的基本語法
// 存取修飾詞 回傳型別 方法名稱(參數列表)
// {
//     方法本體
//     return 回傳值;
// }

// 有回傳值的方法
static int Add(int a, int b)  // 接收兩個整數,回傳一個整數
{
    return a + b;  // 回傳兩數相加的結果
}

// 沒有回傳值的方法(void)
static void SayHello(string name)  // 接收一個字串,不回傳任何值
{
    Console.WriteLine($"你好,{name}!");  // 印出問候語
}

// 呼叫方法
int sum = Add(3, 5);        // 呼叫 Add 方法,傳入 3 和 5
Console.WriteLine(sum);      // 輸出:8

SayHello("小明");          // 呼叫 SayHello 方法
// 輸出:你好,小明!

📌 ref、out、params 關鍵字

// ref — 傳參考(方法內的修改會影響外面的變數)
static void Double(ref int number)  // ref 表示傳入變數的參考
{
    number *= 2;  // 直接修改原來的變數
}

int value = 10;                  // 原始值是 10
Double(ref value);               // 用 ref 傳入
Console.WriteLine(value);        // 輸出:20(原始變數被修改了!)

// out — 輸出參數(方法必須在裡面賦值)
static void Divide(int a, int b, out int quotient, out int remainder)
{
    quotient = a / b;   // 商數(必須賦值)
    remainder = a % b;  // 餘數(必須賦值)
}

Divide(10, 3, out int q, out int r);  // 呼叫時用 out 宣告變數
Console.WriteLine($"商:{q},餘:{r}"); // 輸出:商:3,餘:1

// 實際範例:int.TryParse 就是用 out 的好例子
if (int.TryParse("42", out int parsed))  // out 接收轉換結果
{
    Console.WriteLine($"轉換成功:{parsed}"); // 輸出:轉換成功:42
}

// params — 可變數量參數(接受任意數量的參數)
static int Sum(params int[] numbers)  // params 讓你傳入任意多個整數
{
    int total = 0;                     // 總和初始值
    foreach (int n in numbers)         // 走訪所有傳入的數字
    {
        total += n;                    // 累加
    }
    return total;                      // 回傳總和
}

Console.WriteLine(Sum(1, 2, 3));           // 傳入 3 個參數 → 6
Console.WriteLine(Sum(1, 2, 3, 4, 5));     // 傳入 5 個參數 → 15
Console.WriteLine(Sum());                   // 傳入 0 個參數 → 0

📌 選擇性參數與具名引數

// 選擇性參數(Optional Parameters)— 有預設值的參數
static void Greet(string name, string greeting = "你好", int times = 1)
{
    for (int i = 0; i < times; i++)          // 重複印出 times 次
    {
        Console.WriteLine($"{greeting},{name}!"); // 印出問候語
    }
}

Greet("小明");                    // 使用所有預設值 → 你好,小明!
Greet("小明", "哈囉");          // 覆蓋 greeting → 哈囉,小明!
Greet("小明", "嗨", 3);         // 覆蓋兩個預設值,印 3 次

// 具名引數(Named Arguments)— 指定參數名稱
Greet(name: "小美", times: 2);    // 跳過 greeting,只設 times
Greet(times: 3, name: "小華", greeting: "早安"); // 順序可以不同

📌 方法多載(Method Overloading)

// 方法多載:同名方法,但參數不同
static int Multiply(int a, int b)       // 整數版本
{
    return a * b; // 兩個整數相乘
}

static double Multiply(double a, double b)  // 浮點數版本
{
    return a * b; // 兩個浮點數相乘
}

static int Multiply(int a, int b, int c)    // 三個參數版本
{
    return a * b * c; // 三個整數相乘
}

// 編譯器會根據傳入的參數自動選擇正確的版本
Console.WriteLine(Multiply(3, 4));         // 呼叫 int 版本 → 12
Console.WriteLine(Multiply(2.5, 3.0));     // 呼叫 double 版本 → 7.5
Console.WriteLine(Multiply(2, 3, 4));      // 呼叫三參數版本 → 24

📌 表達式主體方法(Expression-bodied Methods)

// 如果方法本體只有一行,可以用 => 簡化
static int Square(int x) => x * x;  // 回傳 x 的平方

static bool IsEven(int n) => n % 2 == 0;  // 判斷是否為偶數

static string GetGreeting(string name) => $"Hello, {name}!"; // 回傳問候語

static void PrintLine() => Console.WriteLine("---");  // 印出分隔線

// 使用
Console.WriteLine(Square(5));           // 輸出:25
Console.WriteLine(IsEven(4));           // 輸出:True
Console.WriteLine(GetGreeting("小明")); // 輸出:Hello, 小明!

📌 區域函式(Local Functions)

// 區域函式:在方法裡面定義的方法
static int Factorial(int n) // 計算階乘(n!)
{
    // 驗證輸入
    if (n < 0) throw new ArgumentException("n 不能是負數"); // 檢查參數

    // 區域函式:只有 Factorial 方法內部能使用
    int Calculate(int num) // 遞迴計算階乘
    {
        if (num <= 1) return 1;            // 基底條件:0! = 1! = 1
        return num * Calculate(num - 1);    // 遞迴:n! = n * (n-1)!
    }

    return Calculate(n);  // 呼叫區域函式
}

Console.WriteLine(Factorial(5));  // 5! = 5*4*3*2*1 = 120

// 區域函式的好處:
// 1. 把輔助邏輯封裝在使用它的方法裡
// 2. 可以存取外層方法的變數
// 3. 比 private 方法更能表達「這只是內部使用」
static void ProcessData(int[] data) // 處理資料的方法
{
    int threshold = 50;  // 門檻值

    // 區域函式可以存取外層的 threshold 變數
    bool IsAboveThreshold(int value) => value > threshold; // 判斷是否超過門檻

    foreach (var item in data) // 走訪每個資料
    {
        if (IsAboveThreshold(item))   // 使用區域函式判斷
        {
            Console.WriteLine($"{item} 超過門檻 {threshold}"); // 印出結果
        }
    }
}

🤔 我這樣寫為什麼會錯?

❌ 錯誤:忘記 return

// ❌ 錯誤:宣告了回傳型別但沒有 return
static int GetMax(int a, int b)
{
    if (a > b)
    {
        return a;   // 有 return
    }
    // 如果 a <= b 呢?沒有 return!→ 編譯錯誤
}

// ✅ 正確:所有分支都要有 return
static int GetMaxFixed(int a, int b)
{
    if (a > b)
    {
        return a;  // a 較大時回傳 a
    }
    return b;      // 否則回傳 b
}

❌ 錯誤:params 不是放在最後

// ❌ 錯誤:params 必須是最後一個參數
// static void Test(params int[] numbers, string name) { }

// ✅ 正確:params 放最後
static void Test(string name, params int[] numbers) // params 在最後
{
    Console.WriteLine($"{name}: {numbers.Length} 個數字");
}

❌ 錯誤:out 參數沒有賦值

// ❌ 錯誤:out 參數必須在方法內賦值
// static void GetValue(out int x)
// {
//     // 忘記給 x 賦值 → 編譯錯誤
// }

// ✅ 正確:一定要給 out 參數賦值
static void GetValue(out int x)
{
    x = 42;  // out 參數一定要賦值
}

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊