首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 參數傳遞機制詳解:值傳遞與引用傳遞的差異與應用

     編輯:關於C語言

引言:參數傳遞的兩種基本模式

在 C# 程式設計中,方法參數的傳遞方式直接影響資料在呼叫端與被呼叫端之間的流向與修改權限。預設情況下,C# 採用值傳遞:呼叫時將實際引數的副本傳給形式參數,方法內部對參數的任何修改都不會影響原始變數。若需讓方法能直接修改呼叫端的變數,則必須使用引用傳遞(以 ref 或 out 關鍵字標記)。本文將透過完整範例,深入剖析兩者的行為差異、適用場景,並延伸介紹 Main 方法簽章、結構體方法與委托基礎等核心概念。

一、值傳遞:預設的安全隔離機制

值傳遞建立的是實參的獨立副本。以下範例示範 double 型別以值方式傳遞時,方法內部修改不影響外部變數:

static void DoDouble(double myNum)
{
    myNum *= 2;
    Console.WriteLine($"方法內 myNum = {myNum}");
}

static void Main()
{
    double myNum = 15;
    Console.WriteLine($"呼叫前 myNum = {myNum}");
    DoDouble(myNum);
    Console.WriteLine($"呼叫後 myNum = {myNum}"); // 仍為 15
}

值傳遞執行結果

輸出顯示:Main 中的 myNum 始終保持 15 不變。若需將運算結果帶回呼叫端,可改用回傳值:

static double DoDouble(double myNum)
{
    myNum *= 2;
    Console.WriteLine($"方法內 myNum = {myNum}");
    return myNum;
}

static void Main()
{
    double myNum = 15;
    Console.WriteLine($"呼叫前 myNum = {myNum}");
    myNum = DoDouble(myNum); // 接收回傳值
    Console.WriteLine($"呼叫後 myNum = {myNum}"); // 變為 30
}

回傳值修改變數

但回傳值僅能帶回單一結果,若需同時修改多個引數,則必須改用引用傳遞。

二、引用傳遞:ref 關鍵字實現雙向綁定

在參數宣告與呼叫處同時加上 ref,形式參數將成為實際引數的別名,兩者指向同一記憶體位址:

static void DoDouble(ref double myNum)
{
    myNum *= 2;
    Console.WriteLine($"方法內 myNum = {myNum}");
}

static void Main()
{
    double myNum = 15;
    Console.WriteLine($"呼叫前 myNum = {myNum}");
    DoDouble(ref myNum); // 傳遞引用
    Console.WriteLine($"呼叫後 myNum = {myNum}"); // 變為 30
}

引用傳遞執行結果

此時輸出與回傳值版本一致,但 ref 允許方法同時修改多個引數,且不需透過回傳值傳遞結果。

三、Main 方法:程式的進入點與參數接收

C# 應用程式的執行起點固定為 Main 方法,其合法簽章包含:

  • static void Main()
  • static void Main(string[] args)
  • static int Main()
  • static int Main(string[] args)

args 陣列用於接收命令列參數,使程式能從外部獲取啟動資訊。Main 執行結束即代表程式結束。

四、結構體與實例方法:封裝資料與行為

結構體(struct)同樣可定義方法,將資料操作邏輯封裝於型別內部。範例定義 Cloth 結構體並提供 SellPrice 方法計算折扣價:

struct Cloth
{
    public int Age;
    public string Sex;
    public string Style;
    public double Price;
    public double Discount;

    public double SellPrice() => Discount * Price;
}

// 使用範例
Cloth myCloth = new Cloth();
myCloth.Age = 2;
myCloth.Discount = 0.98;
myCloth.Price = 1000;
myCloth.Sex = "man";
myCloth.Style = "長褲";

Console.WriteLine($"出售價格: {myCloth.SellPrice()}"); // 980

結構體方法執行結果

若無實例方法,呼叫端需自行撰寫 myCloth.Price * myCloth.Discount,不僅分散邏輯且易出錯。

五、委托基礎:將方法作為資料傳遞

委托(delegate)是一種型別安全的函式指標,允許將方法簽名相容的方法指派給變數,並在執行期動態調用。宣告委托類似方法簽名但無主體:

delegate double ProcessDelegate(double p1, double p2);

static double Multiply(double a, double b) => a * b;
static double Divide(double a, double b) => a / b;

// 使用委托
ProcessDelegate process = new ProcessDelegate(Multiply);
Console.WriteLine(process(16, 4)); // 64

process = new ProcessDelegate(Divide);
Console.WriteLine(process(16, 4)); // 4

委托執行結果

委托是事件機制的基石,亦是泛型委托(Func、Action)、Lambda 運算式、LINQ 等進階特性的基礎。

總結

  • 值傳遞:預設行為,保護原始資料不被意外修改,適合唯讀輸入。
  • 引用傳遞(ref/out):讓方法直接操作呼叫端變數,適用於需修改多個引數或大型結構體避免複製開銷的場景。
  • 回傳值:單一結果傳回的標準方式。
  • 結構體方法:將資料與操作封裝,提高內聚性。
  • 委托:實現方法的第一級公民地位,支援回呼、事件、策略模式等設計。

掌握參數傳遞機制是編寫健壯、高效 C# 程式的關鍵基石。

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