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

.NET 參數傳遞本質:ref/out 只是「傳址」,所有參數皆為「傳值」

     編輯:關於.NET

許多開發者誤以為「參考型別預設傳址、實值型別預設傳值」,實則 **所有參數預設皆為傳值(複製)**。ref/out 在 IL 層級相同(byref),差別僅在語法規則:ref 需預先指派、out 不需。本文以堆疊記憶體佈局、暫存器狀態、反組譯碼為證,徹底釐清參數傳遞機制。

反直覺範例

void Change2(object o) { o = new object(); }
object obj = null;
Change2(obj);
Console.WriteLine(obj ?? "null"); // 輸出 null

obj 的值(參考位址)被複製給參數 o,方法內修改 o 只改變區域複本,不影響原變數。

ref/out 底層實證:堆疊位址傳遞

static void Ref_Out(ref int a, out int b, int c)
{ a = 15; b = 127; c = 99; }

int i1 = -1; int i2;
Ref_Out(ref i1, out i2, i1);
// i1=15, i2=127

偵錯器觀察呼叫約定(x86):

  • a (ref) → EDI 存放 i1 位址 0x0012F444
  • b (out) → ESI 存放 i2 位址 0x0012F440
  • c (byval) → 堆疊 [EBP+8] 存放值 -1

反組譯碼對照

// a = 15
mov dword ptr [edi], 0Fh     // 解參考 EDI 寫入

// b = 127
mov dword ptr [esi], 7Fh     // 解參考 ESI 寫入

// c = 99
mov dword ptr [ebp+8], 63h   // 直接覆寫堆疊複本

方法返回後,i1/i2 已被修改,c 的複本隨堆疊框架銷毀。

結論

  • **參數傳遞永遠是複製**;
  • ref/out 複製的是**變數位址**(Managed Pointer),方法內解參考即可修改原變數;
  • 參考型別傳值複製的是**參考**,故可修改物件內容,但無法換掉原變數指向的物件;
  • 理解底層機制,方能避免「以為修改了參數卻沒生效」的常見錯誤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved