首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

全面認識 C#(十四):參數修飾詞 - ref/out/in/params

     編輯:C# 入門

前言

C# 提供豐富的參數修飾詞,精確控制引數傳遞語意:值傳遞、參考傳遞、輸出參數、唯讀參考、可變參數,解決 C++ 參數模糊、Java 缺乏參考傳遞的問題。

參數修飾詞完整對照

修飾詞傳遞語意呼叫端被呼叫端適用場景
(無)值傳遞 (參考型別傳參考複製)無無預設,輸入參數
ref參考傳遞 (雙向)refref需修改呼叫端變數、交換值
out輸出參數 (單向寫入)outout多重回傳值、TryParse 模式
in唯讀參考傳遞 (C# 7.2+)inin大型結構避免複製、保證不修改
params可變參數陣列無/陣列params參數數量不固定

ref 參考傳遞


public static void Swap(ref int a, ref int b) {
    (a, b) = (b, a); // C# 7.0 元組交換
}

// 呼叫
int x = 1, y = 2;
Swap(ref x, ref y); // 呼叫端也必須加 ref
Console.WriteLine($"{x}, {y}"); // 2, 1

ref 回傳與 ref 區域變數 (C# 7.0+)


public ref int FindFirstEven(int[] numbers) {
    for (int i = 0; i < numbers.Length; i++)
        if (numbers[i] % 2 == 0) return ref numbers[i];
    throw new InvalidOperationException();
}

// 使用
int[] nums = { 1, 3, 4, 5 };
ref int even = ref FindFirstEven(nums);
even = 10; // 修改陣列元素
Console.WriteLine(nums[2]); // 10

out 輸出參數


public static bool TryParseInt(string s, out int result) {
    return int.TryParse(s, out result); // 內建模式
}

// 使用
if (TryParseInt("42", out int value)) 
    Console.WriteLine(value); // 42

// C# 7.0+ 內嵌宣告
if (int.TryParse("123", out var num)) 
    Console.WriteLine(num);

in 唯讀參考 (C# 7.2+)


public readonly struct LargeStruct {
    public double X, Y, Z, W, A, B, C, D;
    public double Magnitude => Math.Sqrt(X*X + Y*Y + Z*Z + W*W + A*A + B*B + C*C + D*D);
}

public static double Compute(in LargeStruct s) { // 避免複製 64 bytes
    return s.Magnitude;
    // s.X = 1; // 編譯錯誤:唯讀
}

// 使用
var s = new LargeStruct { X = 1, Y = 2 };
double m = Compute(s); // 隱含 in 傳遞
double m2 = Compute(in s); // 明確 in

in 的防禦性複製

  • 呼叫非 readonly 方法/屬性時,編譯器建立防禦性複製
  • 標記結構 readonly struct 避免複製

params 可變參數


public static int Sum(params int[] numbers) {
    int sum = 0;
    foreach (int n in numbers) sum += n;
    return sum;
}

// 使用
Sum(1, 2, 3);        // 6
Sum(new[] { 1,2,3 }); // 6
Sum();               // 0
Sum(Array.Empty()); // 0

params 與 Span (C# 13+ / .NET 8+)


public static int Sum(params ReadOnlySpan numbers) { // 避免陣列配置
    int sum = 0;
    foreach (int n in numbers) sum += n;
    return sum;
}

C++ 對比:參數模糊問題


// C++: 呼叫端無法區分傳值/傳參考
void Func1(int x) { }      // 傳值
void Func2(int& x) { }     // 傳參考
void Func3(int* x) { }     // 傳指標

int a = 1;
Func1(a);  // 傳值
Func2(a);  // 傳參考 - 呼叫端語法相同!
Func3(&a); // 傳指標 - 需取址

C# 強制呼叫端標註 ref/out/in,消除模糊,提升可讀性與安全性。

Java 對比:缺乏參考傳遞

  • Java 只有值傳遞 (參考型別傳參考複製)
  • 模擬參考傳遞:傳遞單元素陣列、包裝類別、AtomicReference
  • C# 直接語言支援,更直觀高效

最佳實務

  1. 輸入參數預設 無修飾詞 (值傳遞/參考複製)
  2. 需修改呼叫端變數用 ref
  3. 多重回傳/Try 模式用 out
  4. 大型結構 (>= 16 bytes) 唯讀輸入用 in + readonly struct
  5. 參數數量不定用 params,僅限最後一個參數
  6. 避免 ref/out 過度使用,考慮回傳 Tuple/Record/物件

總結

C# 參數修飾詞提供精確的傳遞語意控制:ref 雙向、out 輸出、in 唯讀參考、params 可變參數。呼叫端強制標註消除 C++ 模糊問題,補足 Java 缺失。善用 in + readonly struct 可大幅提升大型值型別效能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved