ref、out、params 三個關鍵字雖可能違反純粹 OO 原則,但 C# 內建支援,理解其差異對正確設計方法簽章至關重要。
params:可變參數陣列
- 允許方法接受不定數量引數,內部視為陣列。
- 限制:只能出現在參數列表最後,且每個方法僅能有一個
params 參數。
public static void UseParams(params int[] list) { /* ... */ }
public static void UseParams2(params object[] list) { /* ... */ }
// 呼叫
UseParams(1, 2, 3);
UseParams(1, 2);
UseParams2(1, 'a', "test");
UseParams(new int[] { 10, 11, 12 }); // 也可傳陣列
out:輸出參數 (必指派)
| 規則 | 說明 |
| 呼叫端 | 引數不需初始化,但必須加 out 關鍵字。 |
| 方法內 | 參數進入時被清空,必須在返回前指派值 (否則編譯錯誤)。 |
| 用途 | 方法需回傳多個值時(仍可有一個傳回值)。 |
| 限制 | 屬性不能作為 out 引數;不可與 ref 同名構成多載。 |
ref:參考傳遞 (雙向)
| 規則 | 說明 |
| 呼叫端 | 引數必須先初始化,並加 ref 關鍵字。 |
| 方法內 | 參數保留原值,可讀可寫,修改會反映回呼叫端。 |
| 限制 | 不可與 out 同名構成多載;屬性不可作 ref 引數。 |
多載規則速查
// 有效多載:參數修飾符不同
void M(int i) { }
void M(out int i) { i = 10; }
void M(ref int i) { i = 10; }
// 無效多載:僅 ref/out 差異
void M(out int i) { }
void M(ref int i) { } // 編譯錯誤 CS0663
實戰比較範例
static string TestOut(out string o) { o = "out b"; return "ret"; }
static void TestRef(ref string r) { r = "ref b"; }
static void TestNone(string n) { n = "none c"; }
// 呼叫
string outVal; // 無需初始化
TestOut(out outVal); // outVal = "out b"
string refVal = "a"; // 必須初始化
TestRef(ref refVal); // refVal = "ref b"
TestNone(refVal); // refVal 維持 "ref b" (傳值不影響)
選擇指南
- 需回傳多個值、且呼叫端無預設值 →
out。
- 需雙向傳遞、呼叫端已有初始值 →
ref。
- 參數數量不固定 →
params。
- 一般情況 → 傳值 (預設) 最安全、最符合 OO 封裝。